;;; -*-Midas-*-
;;; Copyright (c) 1999 Massachusetts Institute of Technology
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, see https://gnu.org/licenses or
;;; write to:
;;;  Free Software Foundatiom, Inc.
;;;  51 Franklin St, Fifth Floor
;;;  Boston, MA 02110-1301
;;;  USA

		.TITLE IOELEVEN

	.SBTTL DEFINITIONS

;;; note that the .IFM macro must be used only at toplevel
;;; (non-conditionalized) in PALX because it doesn't do the expansion of .IFM
;;; when conditionalized out, therefore it doesn't match it with the
;;; following .ENDC and the .ENDC will be seen at toplevel and end the
;;; conditionalization one is in.  This will screw the code running on
;;; another one of the machines even if it doesn't signal an error in your
;;; assembly.  --PGS 

.LIF NZ 0
 .FATAL USE PALX DUMMY!!

;NOTE THAT THIS PROGRAM IS DESIGNED FOR 11/40'S.  TO RUN ON AN
;11/10, MACRO OUT THE SOB INSTRUCTIONS.  DOES NOT USE EIS NOR FIS.

A=%0		;TEMP/ARG/CHAR
B=%1		;TEMP/ARG
C=%2		;TEMP/ARG
D=%3		;TEMP/ARG
H=%4		;USUALLY INDEX IN HARDWARE UNIT TABLES
I=%5		;USUALLY LINE NUMBER TIMES 2
SP=%6		;STACK POINTER
PC=%7		;PROGRAM POINTER
PS=177776	;PROGRAM STATUS
SWR=177570	;SWITCHES

.MACRO RTI
.ENDM ;FUCKING PALX!

RTI=RTT		;11/40 HARDWARE MISFEATURE

.IF P1
.PRINT /MACHINE NAME = /
.TTYMAC MNAM
%TTYFLG==%TTYFLG+1
.PRINT /MNAM
/
%TTYFLG==%TTYFLG-1
.MACRO .IFM MCHN		;REFERS TO PDP11 NAME
.IF IDN MCHN,MNAM
.ENDM .IFM
.MACRO MCONDX MCHN		;REFERS TO ITS SYSTEM NAME, USUALLY THE SAME
.IF IDN MCHN,MNAM
.ENDM MCONDX
.MACRO FUBAR
.ENDC
.ENDC
.ENDM FUBAR
.MACRO MNAME BODY		;INSERT ITS SYSTEM NAME INTO BODY IN PLACE OF "MCHN"
.IRP MCHN,<MNAM>
BODY
.ENDM
.ENDM MNAME
.ENDM ;TTYMAC
.ENDC ;P1

VERSION==%FNAM2

.IFM MC-DL			;MC'S DL-10 PDP11
.MACRO MCONDX MCHN
.IF IDN MCHN,MC
.ENDM MCONDX
.MACRO FUBAR
.ENDC
.ENDM FUBAR
.MACRO MNAME BODY
.IRP MCHN,<MC>
BODY
.ENDM
.ENDM MNAME

DL10P==1	;HAS DL10
DTE20P==0	;DOES NOT HAVE DTE20
NODDT==0	;HAS DDT
NFTTY==102	;2 * # OF FIRST TTY THIS 11
NDHS==1		;NUMBER OF DH11'S
NDHUN==15	;NUMBER OF UNUSED DH11 LINES
DHIBAS==320	;DH11 INTERRUPT VECTOR BASE
DHCBAS==160020	;CSR of first DH11 
NDLS==1		;NUMBER OF DL11'S
CTYP==0		;FIRST DL11 NOT T00 (CTY)
NMPTYS==0	;NUMBER OF TTYS ON MULTIPLEXED LINE (REST IN PEACE)
;MPXIDX==2*27	;TTY INDEX OF LINE THAT MULTIPLEXED TTYS RUN OVER
NDMS==0		;HAS DM11BB MODEM SCANNER (BUT IT'S NOT CONNECTED TO ANYTHING)
GOULDP==0	;DOESN'T HAVE GOULD LPT (ANYMORE)
T300P==1	;TRIDENT T-300 AND 2561 CONTROLLER
CHAOSP==2	;HAS TWO CHAOS NET INTERFACES
CHSBTB=0	;CHAOSNET INTERFACE IS NEW, DOESN'T GET HUNG ANY MORE
CHAD0==440	;CHAOSNET ADDRESS OF THIS PDP11 ITSELF
DLCADR==1440	;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA DL10 (MC)
CHAD1==3040	;SECOND INTERFACE
TEN11P==0	;NO TEN-11 INTERFACE
ETHERP==0	;NO ETHERNET
FTPULS==0	;INITIALLY, MC DOES NOT GENERATE TEST PACKETS
FTGARB==1	;SAVE LAST GARBAGE PACKET RECEIVED
MAXBSZ==250.	;MAXIMUM TYPEOUT BUFFER SIZE
.MACRO ASPIRP BODY	;DEFINE LINE NUMBERS WITH AUTOSPEED
.ENDM ASPIRP
.ENDC ;MC-DL

.IFM MC		;MC CONSOLE 11
DL10P==0	;DOES NOT HAVE DL10
DTE20P==1	;HAS DTE20
NODDT==0	;HAS DDT AND KLDCP
NFTTY==0	;2 * # OF FIRST TTY THIS 11
NDHS==2		;NUMBER OF DH11'S
NDHUN==0	;NUMBER OF UNUSED DH11 LINES
DHIBAS==310	;DH11 INTERRUPT VECTOR BASE
DHCBAS==160020	;CSR of first DH11 
NDLS==1		;NUMBER OF DL11'S
CTYP==1		;FIRST DL11 IS T00 (CTY)
NMPTYS==0	;NUMBER OF TTYS THAT GO THROUGH MULTIPLEXED LINE (NONE)
NDMS==2		;has 2 DM11BB modem scanners (really DH11AD)
GOULDP==0	;DOESN'T HAVE GOULD LPT
T300P==0	;TRIDENT T-300 AND 2561 CONTROLLER
CHAOSP==0	;NO CHAOS NET INTERFACE
TEN11P==0	;NO TEN-11 CHAOS INTERFACE
ETHERP==0	;NO ETHERNET
MAXBSZ==250.	;MAXIMUM TYPEOUT BUFFER SIZE

.MACRO ASPIRP BODY	;DEFINE LINE #S WITH AUTOSPEED
.IRP N,<1,3,4,5,6,7,10,11,12,13,14,15,16,17>
	BODY
.ENDM
.ENDM ASPIRP

TKS==177560
TKB==177562
TPS==177564
TPB==177566
.ENDC ;MC

.IFM AI		;AI'S CHAOS-ETHER-GATEWAY PDP11

;THIS IS A PDP11/10, WE HAVE TO REDEFINE A FEW THINGS
.MACRO RTT
.ENDM
RTI==2
RTT==2
.MACRO SOB REG,TAG
	DEC REG
	BNE TAG
.ENDM SOB

DL10P==0	;HAS NO DL10
DTE20P==0	;DOES NOT HAVE DTE20
NODDT==1	;DOESN'T HAVE DDT (USE CARPET)
NFTTY==0	;2 * # OF FIRST TTY THIS 11
NDHS==0		;NUMBER OF DH11'S
NDHUN==0	;NUMBER OF UNUSED DH11 LINES
DHIBAS==320	;DH11 INTERRUPT VECTOR BASE
DHCBAS==160020	;CSR of first DH11 
NDLS==0		;NUMBER OF DL11'S  (ACTUALLY HAS ONE, BUT WE'RE NOT USING IT NOW)
CTYP==0		;FIRST DL11 NOT T00 (CTY)
NMPTYS==0	;NUMBER OF TTYS ON MULTIPLEXED LINE
NDMS==0		;HAS NO DM11BB MODEM SCANNERS
GOULDP==0	;DOESN'T HAVE GOULD LPT
T300P==0	;TRIDENT T-300 AND 2561 CONTROLLER
CHAOSP==2	;HAS TWO CHAOS NET INTERFACES
CHSBTB==0	;CHAOSNET INTERFACE IS NEW-STYLE, DOES NOT GET HUNG
;CHAD0==426	;CHAOSNET ADDRESS OF THIS PDP11 ITSELF (AI-MC-CROSS-STREET SUBNET)
;CHAD1==3072	;SECOND INTERFACE (9TH FLOOR LISP MACHINE SUBNET)
CHAD0==3072	;Change these two around because subnet 1 is dying of old age.
CHAD1==426	;Note that with current code AI-11 can only do DOVER on CHAD0!!
TEN11P==0	;USES TEN-11 INTERFACE FOR CHAOS NET TO AI-10  (NOT ANY MORE!)
T11ADR==2026	;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA TEN-11 INTERFACE (AI)
NT11BF==3	;THREE BUFFERS IN EACH DIRECTION FOR TEN-11 INTERFACE
ETHERP==1	;ETHERNET
ETHHSN==6	;MY HOST NUMBER BYTE, JNC SAYS I SHOULD USE 6
NDVRBF==6	;6 DOVER BUFFERS
DVRADR==1002	;PUP ADDRESS OF DOVER
FTPULS==0	;INITIALLY, AI DOES NOT GENERATE TEST PACKETS
FTGARB==1	;DON'T SAVE LAST GARBAGE PACKET RECEIVED (LOW ON CORE) (not that low)
MAXBSZ==250.	;MAXIMUM TYPEOUT BUFFER SIZE
.MACRO ASPIRP BODY	;DEFINE LINE NUMBERS WITH AUTOSPEED
.ENDM ASPIRP
.ENDC ;AI

.IIF NDF NDHS, .ERROR MACHINE NAME NOT RECOGNIZED

.IIF NZ DL10P, .IIF Z NFTTY, .ERROR TTY # 0 DOESN'T WORK WITH DL10 PROTOCOL

;ASSIGN TTY INDICES, HARDWARE INDICES, ETC.

TX==NFTTY	;TTY INDEX
HX==0		;HARDWARE INDEX
NCT==0		;NUMBER OF TTYS

;SYSTEM CONSOLE (OUT OF ORDER)
.IFNZ CTYP
	TX==TX+2
	NCT==NCT+1
.ENDC

;DH11 LINES
	NFDHTY==TX
	TX==TX+<32.*NDHS>
	NCT==NCT+<16.*NDHS>
	HX==HX+<2*NDHS>
	NLDHHX==HX-2		;UNITS 0-NLDHHX INCLUSIVE ARE DH11S

	TX==TX-<2*NDHUN>	;COMPENSATE FOR UNUSED LINES
	NLDHTY==TX-2		;LAST DH11 LINE INCLUSIVE
	NCT==NCT-NDHUN

;DL11 LINES
	NFDLTY==TX
	NFDLHX==HX
	TX==TX+<2*NDLS>-<2*CTYP>
	HX==HX+<2*NDLS>
	NLDLHX==HX-2
	NCT==NCT+NDLS-CTYP

;MULTIPLEXOR LINES
	NFMPTY==TX
	MPKHWR==HX
	TX==TX+<2*NMPTYS>
	HX==HX+2
	NCT==NCT+NMPTYS

NLTTY==NFTTY+<2*NCT>	;2 * # OF FIRST TTY NOT THIS 11
LASTTY==NLTTY-2		;LAST VALID TTY INDEX

.IFNZ NDMS	;DM11-BB MODEM SCANNER

		;1.1-1.4 MODEM CHANNEL #
 DMBSY==20	;1.5 SCAN BUSY (R.O.)
 DMSCN==40	;1.6 SCANNER ON
 DMIEN==100	;1.7 INTERRUPT ENABLE
 DMDON==200	;1.8 DONE - SCANNER HAS FOUND SOMETHING
 DMSTP==400	;1.9 STEP SCANNER TO NEXT LINE (W.O.) 1.2 USEC.
		;2.1 MAINTENANCE MODE
 DMCLR==2000	;2.2 CLEAR RTS, DTR, SEC TX, LINE EN FOR ALL LINES (W.O.)
 DMCSN==4000	;2.3 CLEAR SCAN - CLEAR CSR AND MODEM STATUS MEMORY (W.O.) 19 USEC
 DM2RX==10000	;2.4 SECONDARY RECIEVE CHANGED ON SELECTED MODEM (R.O.)
 DMCTS==20000	;2.5 CLEAR TO SEND CHANGED ON SELECTED MODEM (R.O.)
 DMCAR==40000	;2.6 CARRIER DETECT CHANGED ON SELECTED MODEM (R.O.)
 DMRNG==100000	;2.7 RING CHANGED ON SELECTED MODEM (R.O.)

 LINENB==1	;1.1 ENABLE SCANNING OF LINE
 LINDTR==2	;1.2 DATA TERMINAL READY
 LINRQS==4	;1.3 REQUEST TO SEND (FORCE BUSY ON 103E)
 LIN2TX==10	;1.4 SECONDARY TRANSMIT
 LIN2RX==20	;1.5 SECONDARY RECEIVE (R.O.)
 LINCTS==40	;1.6 CLEAR TO SEND (R.O.)
 LINCAR==100	;1.7 CARRIER DETECT (R.O.)
 LINRNG==200	;1.8 RING (R.O.)
.ENDC ;NDMS

; KW11-L LINE FREQ CLOCK

LKS=177546	;1.8 CLOCK FLAG
		;1.7 INTER ENB
HNGDLY==3*60.	;CLEAR TO SEND OFF FOR 3 SECONDS => HANGUP

.IFNZ GOULDP
;DEFINITIONS FOR GOULD LPT

GLPCSR=166000	;COMMAND STATUS REGISTER (NONSTANDARD)
 ;COMMAND CODES
 %GCFF==0	;TOP-OF-FORM COMMAND
 %GCGRF==1	;GRAPHIC MODE COMMAND
 %GCCUT==2	;CUT COMMAND (NO CUTTER ON THIS MACHINE, THOUGH)
 %GCON==3	;TURN PRINTER ON
 %GCOFF==4	;TURN PRINTER OFF
 %GCLSL==5	;LAST LINE (GRAPHIC MODE).  => 2 MORE SCAN LINES.
 %GCION==6	;INTERRUPT ON
 %GCIOF==7	;INTERRUPT OFF
 %GCADV==201	;ADVANCE ONE LINE
 ;STATUS BITS
 %GSNRD==400	;NOT READY
 %GSDON==2000	;TRANSFER COMPLETE
 %GSBSY==4000	;BUSY
 %GSVAC==10000	;VACUUM FAULT
 %GSPAP==20000	;PAPER LOW
 %GSTIM==40000	;TIMEOUT
 %GSERR==50400	;ALL ERROR BITS

GLPWC=166002	;NEGATIVE WORD COUNT REG

GLPCA=166004	;CURRENT ADDRESS REG

GLPBSZ==132.	;BUFFER SIZE (# CHARS PER LINE)

NGLPBF==7	;NUMBER OF BUFFERS
 GB.STA==0	;BUFFER STATE - DON'T CHANGE ORDER OF %GB CODES
  %GBIDL==0	;0 IDLE
  %GBMP==2	;2 ACTIVE AT M.P. LEVEL
  %GBWRT==4	;4 IN WRITE QUEUE
  %GBPI==6	;6 ACTIVE AT P.I. LEVEL
  %GBDMA==8	;8 ACTIVE AT D.M.A. LEVEL
 GB.NXT==2	;CIRC POINTER TO NEXT BUFFER
 GB.FF==4	;IF NON-ZERO, FF BEFORE THIS BUFFER
 GB.NL==6	;NUMBER OF BLANK LINES BEFORE THIS BUFFER
 GB.PNT==10	;-> NEXT BYTE TO INSERT
 GB.DAT==12	;DATA BEGINS HERE
 GB.LEN==GB.DAT+GLPBSZ	;TOTAL NUMBER OF BYTES PER BUFFER

.ENDC ;GOULDP

.IFNZ CHAOSP
;DEFINITIONS OF CHAOS NET HARDWARE

;USUAL ADDRESS IS 764140 .  USUAL INTERRUPT VECTOR IS 270 .

CAICSR=164140		;COMMAND STATUS REG
CH%CSR==0
 %CABSY==1		;0 XMT BUSY (RO)
 %CALUP==2		;1 LOOP BACK (R/W)
 %CASPY==4		;2 RECIEVE MSGS FOR ANY DESTINATION (R/W)
 %CARCL==10		;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO)
 %CAREN==20		;4 RCV INT ENB (R/W)
 %CATEN==40		;5 XMT INT ENB (R/W)
 %CATAB==100		;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO)
 %CATDN==200		;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE
 %CATCL==400		;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO)
			;9-12    LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL]
			;        WHEN MSG IS WAITING IN BUFFER, THIS COUNTS
			;        THE MESSAGES THAT MATCHED OUR DESTINATION OR
			;        WERE BROADCAST, BUT COULDN'T BE RECIEVED.
			;	 WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN)
			;	 THE COUNT IS THEN CLEARED.
			;	 WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER
			;	 SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED
			;        TO US.)
 %CARST==20000		;13 I/O RESET (WO)
 %CAERR==40000		;14 CRC ERROR (RO)
 %CARDN==100000		;15  RCV DONE.  

CAIMYN=164142		;MY # (READ ONLY)
CH%MYN==2		;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE.		

CAIWBF=164142		;WRITE BUFFER (WRITE ONLY)
CH%WBF==2		;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR)
			;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE.
			;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE,
			;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT.
			;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE.

CAIRBF=164144		;READ BUFFER (READ ONLY)
CH%RBF==4		;THE FIRST WORD READ WILL BE FILLED TO THE LEFT
			;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS.
			;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A
			;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT
			;INTO THE BUFFER BY THE TRANSMITTING HOST.
			;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK.

CAIRBC=164146		;RECEIVE BIT COUNTER  (READ ONLY)
CH%RBC==6		;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN
			;THE NUMBER OF BITS IN THE MESSAGE (16 X THE
			;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.)
			;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777
			;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE,
			;THEN THERE WAS A BUFFER OVERFLOW

CAIXMT=164152		;READING THIS INITIATES TRANSMISSION (!!)
CH%XMT==12		;THE VALUE READ IS ONE'S OWN HOST#.

;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR
;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE
;STRANGE AND BIZARRE EFFECTS.

;PACKET DEFINITIONS
;THESE ARE FOR 4K PACKET BUFFERS AND FOR THE ORIGINAL CHAOSNET PROTOCOL

PKMAX==256.			;MAXIMUM LENGTH OF PACKET (INCLUDING ALL HARDWARE WORDS)
DATMAX==488.			;MAXIMUM NUMBER OF DATA BYTES
PKHDW==8			;NUMBER OF HEADER WORDS
PKTMXW==<DATMAX/2>+PKHDW	;MAX WORDS THROUGH PACKET SWITCH (SEE MOVDH ETC.)

PKOP==1				;BYTE INDEX OF THE OPCODE OF THE PACKET
 %CORFC==1
 %COOPN==2
 %COCLS==3
 %COANS==5
 %COSNS==6
 %COSTS==7
 %CORUT==10
 %COLOS==11
 %COEOF==14
 %COUNC==15
PKNBYT==2			;WORD INDEX OF NUMBER OF BYTES IN PACKET
PKNBMS==170000			;MASK FOR THE NUMBER OF BYTES
PKFC==2				;WORD INDEX FOR THE FORWARD COUNT
PKFCMS==7777			;IT IS THE TOP 4 BITS
PKDHST==4			;DESTINATION HOST
PKDIND==6			; "   "   "  INDEX
PKSHST==10			;SOURCE HOST
PKSIND==12			;SOURCE INDEX
PKPKN==14			;THE PACKET NUMBER
PKACN==16			;THE ACK PACKET NUMBER
PKDAT==20			;THE START OF THE DATA
.ENDC ;CHAOSP

;STANDARD MACROS

.MACRO PUSH X
.IRP Y,<X>
	MOV Y,-(SP)
.ENDM
.ENDM

.MACRO POP X
.IRP Y,<X>
	MOV (SP)+,Y
.ENDM
.ENDM

.MACRO CALL X
	JSR PC,X
.ENDM

.MACRO RET
	RTS PC
.ENDM

.MACRO SETOM LOC
 ZZ===%COMPAT		;DON'T CARE WHETHER .+2 OR .+4 GETS STORED
 %COMPAT===0
	MOV PC,LOC
 %COMPAT===ZZ
.ENDM

.MACRO MASK LEVEL
	PUSH PS
	MOV #<LEVEL>_5,PS
.ENDM

.MACRO UNMASK
	POP PS
.ENDM

.MACRO W
.=.+2
.ENDM

.MACRO T TAG	;usage is T TAG: <crlf> STMNT
.=.-NFTTY
TAG
.=.+NFTTY
.ENDM

.MACRO CONC A,B,C,D,E,F,G
A'B'C'D'E'F'G
.ENDM

.MACRO INFORM A,B,C,D,E,F,G
.IF P1
.PRINT /A'B'C'D'E'F'G
/
.ENDC
.ENDM

.MACRO MSG X
.NCHR ZZ,^\X\
	.WORD ZZ
	.ASCII \X\
	.EVEN
.ENDM

.MACRO .IREPT N,BOD
.REPT N
BOD
.ENDR
.ENDM
.IFNZ DL10P
	.SBTTL DL10 CONTROL AREA

ZZ==.
.=100000

DLXCSR: W	;DL10 11-SIDE CONTROL & STATUS REG
		;1.1-1.2 PIA
 DLXIEN==4	;1.3 ENABLE DLX11I TO INTERRUPT
 DLXEEN==10	;1.4 ENABLE ERRORS TO INTERRUPT
		;1.5 UNUSED
 DLXPRT==40	;1.6 PORT ENABLE (R.O.)
 DLXZWC==100	;1.7 CLEAR DLXWCO (W.O.)
 DLXWCO==200	;1.8 WORD COUNT OVERFLOW
 DLXZPA==400	;1.9 CLEAR DLXPAR (W.O.)
 DLXPAR==1000	;2.1 PAR ERR IN 10 MEM
 DLXZNX==2000	;2.2 CLEAR DLXNXM (W.O.)
 DLXNXM==4000	;2.3 NXM IN 10 MEM
 DLXZ10==10000	;2.4 CLEAR DLX10I (W.O.)
 DLX10I==20000	;2.5 INTERRUPT PDP10
 DLXZ11==40000	;2.6 CLEAR DLX11I (W.O.)
 DLX11I==100000	;2.7 INTERRUPT PDP11

VERS:	W	;.BYTE FIRST LINE, # OF LINES
		;SET BY -10.  USED TO CHECK CONSISTENCY.

DLXUP:	W	;CHECK FOR UP-NESS IN BOTH DIRECTIONS
		;INCREMENTED BY 11 EVERY 1/60 SECOND, SETOM'ED BY 10 EVERY 1/2 SEC.

TTYST:	W	;LINE# TO START OUTPUT ON (I.E. SET OUTPUT DONE)
		;SET BY 10, CLEARED BY 11

TYILIN:	W	;TYPEIN STATUS WORD - LINE NUMBER
		;SET BY 11, CLEARED BY 10 - INTERRUPTS 10
TYICHR:	W	;TYPEIN CHARACTER - GOES WITH PRECEDING WORD

TYOSTS:	W	;STATUS WORD (OUTPUT DONE LINE #)
		;SET BY 11, CLEARED BY 10 - INTERRUPTS 10
TYOBSZ:	W	;BUFFER SIZE FOR LINE WITH OUTPUT DINE (SET BY 11)

TYOPNT:	W	;BUFFER POINTER FOR TTY OUTPUT
		;SET BY 10
TYOCNT:	W	;BUFFER LENGTH FOR TTY OUTPUT
		;SET BY 10
TYOLIN:	W	;LINE NUMBER FOR TTY OUTPUT
		;SET BY 10, CLEARED BY 11

HNGLIN:	W	;0000NN - LINE # NN HUNG UP
		;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES)
		;SET BY 11, CLEARED BY 10 - INTERRUPTS 10

LPRLIN:	W	;LINE NUMBER FOR SETTING LINE PARAMETERS
		;SET BY 10, CLEARED BY 11
LPRLPR:	W	;DH11 LPR REGISTER FOR SETTING LINE PARAMETERS
		;SET BY 10
LPRBSZ:	W	;BUFFER SIZE FOR SETTING LINE PARAMETERS
		;SET BY 10

EXDSTS:	W	;STATUS WORD (EXAMINE/DEPOSIT 11 CORE)
		;1 = EXAMINE, 2 = DEPOSIT
		;SET BY 10, CLEARED BY 11
EXDADR:	W	;ADDRESS FOR ABOVE
		;SET BY 10
EXDDAT:	W	;DATA WORD FOR ABOVE
		;SET BY 10 (DEPOSIT) OR 11 (EXAMINE)

GLPPTR:	W	;BUFFER POINTER FOR GOULD OUTPUT
GLPCTR:	W	;NUMBER OF BYTES YET TO BE GOBBLED
GLPTER:	W	;ERROR STATUS, SET BY 11
GLPGRF:	W	;GRAPHIC MODE IF NON-ZERO, SET BY 10

;CHAOS NET SHARED VARIABLES
DLCINI:	W	;WHEN THIS IS NON-ZERO, 11 RESETS ITS POINTERS AND CLEARS IT
DLCSP1:	W	;SEND PACKET 1 (ILDB POINTER)
DLCSP2:	W	;SEND PACKET 2
DLCSS1:	W	;SEND STATE 1 (0 IDLE, 1 TO 11, 2 OUTPUT DONE)
DLCSS2:	W	;SEND STATE 2
DLCRP1:	W	;RECEIVE PACKET 1 (ILDB POINTER)
DLCRP2:	W	;RECEIVE PACKET 2
DLCRS1:	W	;RECEIVE STATE 1 (0 IDLE, 1 READY FOR INPUT FROM 11, 2 INPUT DONE)
DLCRS2:	W	;RECEIVE STATE 2

;^ ADD MORE HERE, E.G. IMP

.IFNZ T300P
;DISK AREA.  14. WORDS 48. WORDS INTO THE DL-10 AREA.
.=100000+<60*2>

DSCCHK:	W	;MUST BE 2561 OCTAL TO MAKE SURE WE HAVE CORRECT PDP-10 PROGRAM
DSCREQ:	W	;0 MEANS NO REQUEST.  NON-ZERO MEANS 10 HAS PENDING REQUEST TO 11.
DSCDON:	W	;0 MEANS NOT DONE, NON-ZERO MEANS 11 IS TELLING 10 IT'S DONE.
;NEXT 2 WORDS WRITTEN BY 11 TO TELL STATUS OF OPERATION
DSCFLT:	W	;0 NO FAULT
 %DFRST==100000	; BIT 15=POWER CYCLED OR UNIBUS HUNG, SO CONTROLLER WAS RESET
		; BIT 12=Q ERROR, BIT 11=CMD NXM, BIT 10=CMD PAR
		; IF ONE OF THESE BITS IS ON, BITS 1-0 AND DSCSTS ARE THE ERROR ADDRESS
		; BITS 7-0 SYSTEM FAULT CODE IF LEFT BYTE IS ZERO
		; SEE THE 2561 OEM MANUAL FOR MEANING OF FAULT CODES
DSCSTS:	W	;STATUS FROM 2561:
 %DSRTR==100000	;COMMAND WAS RETRIED
 %DSECH==40000	;UNCORRECTABLE DATA ERROR (ECC HARD)
 %DSECC==20000	;CORRECTED DATA ERROR
 %DSIDE==10000	;ID ERROR
 %DSHCE==4000	;ADDRESS ERROR (HEADER COMPARE ERROR)
 %DSPRT==2000	;WRITE-PROTECT STATUS OF SECTOR (ABORTS WRITE COMMAND)
 %DSALT==1000	;ALTERNATE-SECTOR STATUS (ABORTS READ, WRITE, AND CHECK)
 %DSOVR==400	;FIFO OVER-RUN, NOT CORRECTED BY 1 RETRY
 %DSSKE==200	;SEEK ERROR FROM DRIVE
 %DSOFL==100	;DRIVE OFF-LINE OR FAULT
 %DSFLT==20	;DRIVE FAULT
 %DSNXM==10	;NXM ON PDP11 MEMORY
 %DSPAR==4	;PARITY ERROR IN PDP11 MEMORY
 %DSSFL==2	;SYSTEM FAULT, SEE LOW BYTE OF DSCFLT
 %DSWLK==1	;DRIVE WRITE-LOCKED, WRITE ABORTED

;FOLLOWING WORDS ARE WRITTEN BY 10 TO TELL WHAT TO DO
DSCCMD:	W	;COMMAND OPCODE:
 ;%DMNOP==0	;DO NOTHING
 ;%DMCST==1	;READ OUT CONTROLLER STATE (NOT USEFUL SINCE NOT RETURNED TO 10)
 %DMSNS==2	;SENSE DRIVE STATE.  DSCSTS GETS CODE FOR DRIVE TYPE IN
		; BITS 14-8 (10 FOR T-300), AND %DSWLK, %DSFLT, %DSOFL, %DSSKE
 %DMTST==3	;TEST SPECIFIED DRIVE (RUNS DIAGNOSTICS)
 %DMREC==4	;RECALIBRATE
 %DMSEK==5	;SEEK
 %DMWRT==6	;WRITE DATA
 ;%DMFMT==7	;WRITE FORMAT
 ;%DMPWT==10	;WRITE AND SET WRITE-PROTECT BIT
 ;%DMAWT==11	;WRITE AND SET ALTERNATE-SECTOR BIT
 ;%DMCHK==12	;READ AND CHECK ECC BUT DON'T STORE DATA
 ;%DMLWT==14	;LONG WRITE, WILL WRITE ECC AS WELL AS DATA
 %DMRED==20	;READ DATA.  ADD 1-10 FOR VARIOUS RECOVERY FEATURES AS
		; DOCUMENTED IN THE 2561 OEM MANUAL.
 ;%DMRID==40	;READ IF FIELD, NOT USEFUL SINCE NOT RETURNED TO 10
DSCDRV:	W	;UNIT NUMBER
DSCCYL:	W	;CYLINDER ADDRESS (THESE ARE COPIED BACK BY THE 11 IN CASE OF ERROR)
DSCHED:	W	;HEAD ADDRESS
DSCSEC:	W	;SECTOR ADDRESS
;WORD COUNT IS ALWAYS 12.*256.
;IF WE PUT IN SEEK-OVERLAP AN ATTENTION FEATURE WILL BE NEEDED
;THAT WOULD ALSO BE USED FOR DISK POWER-UP SIGNALLING
;THESE WORDS ARE SET UP BY THE 10 AS BYTE-POINTERS TO THE DATA
;TO BE TRANSFERRED.  EACH BYTE POINTER CAN TRANSFER AT MOST 256 PDP10 WORDS
;DUE TO BRAIN-DAMAGE IN THE DL10, SO THERE ARE 4 OF THEM
DSCPNT:	.BLKW 4
.ENDC ;T300P

DLXHGH::
.=ZZ
.ENDC ;DL10P
.IFNZ DTE20P
	.SBTTL DTE20 CONTROL AREA

;LOCATIONS 400-437 ARE JUST BETWEEN US AND ITS
;LOCATIONS 440-457 ARE KNOWN ABOUT BY KLDCP ALSO

;EPTDDT==441	;START ADDRESS OF PDP10 NON TIME SHARING DDT
DTEFLG==444	;NON TIME SHARING TYPEIN/TYPEOUT DONE FLAG (SET BY 11, CLEARED BY 10)
DTEF11==450	;USED BY NON TIMESHARING TYPEIN COMMAND TO RETURN THE CHAR (SET BY 11)
DTECMD==451	;NON TIME SHARING COMMAND (SET BY 10)
;COMMANDS THAT CAN GO IN DTECMD:
 ;0-377 CHAR TO BE TYPED OUT
 %DTTYI==3400	;TYPE IN, CHAR RETURNED IN DTEF11
 %DTCLN==1001	;60 CYCLE CLOCK ON
 %DTCLF==1000	;60 CYCLE CLOCK OFF
 ;THERE ARE MILLIONS OF OTHERS, BUT WHO NEEDS 'EM?
DTECLK==445	;60 CYCLE CLOCK FLAG (SET BY 11, CLEARED BY 10)
;DTESWR==457	;SIMULATED SWITCH REGISTER (SET BY 11)

;THE FOLLOWING LOCATIONS ARE ONLY USED IN TIME SHARING AND NOT KNOWN ABOUT BY KLDCP

DTEVER==400	;I/O VERSION NUMBER.  .BYTE FIRST LINE, NUMBER OF LINES.
		;SET BY 10, CHECKED BY 11

DTECHK==401	;INCREMENTED BY 11 60 TIMES PER SECOND, SETOMED BY 10 EVERY 1/2 SECOND
		;USED TO CHECK THAT 10 IS GETTING INTERRUPTS OK

DTEINP==402	;CONTROLS "BYTE TRANSFERS" FROM 11 TO 10 (INPUT DIRECTION).
		;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN XFER COMPLETE.
		;10 SHOULD SET UP DTEBPI IN EPT AND DO DATAO DTE, BEFORE SETTING DTEINP.
		;SEE COMMENTS BELOW DTEOUT FOR WHAT GOES IN DTEINP.
DTEOUT==403	;CONTROLS "BYTE TRANSFERS" FROM 10 TO 11 (OUTPUT DIRECTION).
		;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN TRANSFER STARTS.
		;EACH SIDE KNOWS WHEN TRANSFER IS IN PROGRESS, DOESN'T TRY TO START
		; ANOTHER UNTIL IT HAS RECEIVED HARDWARE TRANSFER-DONE INTERRUPT.
		;10 SHOULD SET UP DTEBPO IN EPT BEFORE SETTING DTEOUT.
		;RH IS #BYTES EXPECTED, LH IS COMMAND+LINE#.  COMMANDS ARE:
 %DTTYO==1000	;TELETYPE OUTPUT
 ;%DTETI==2000	;ETHERNET INPUT
 ;%DTETO==3000	;ETHERNET OUTPUT
 ;^ ADD MORE COMMANDS HERE.   NOTE: THE 4.1 BIT IS 1 FOR OUTPUT, 0 FOR INPUT.

DTELSP==404	;LINE# TO SET SPEED OF (SET BY 10, SETOMED BY 11)
DTELPR==405	;DH11 LINE-PARAMETER-REGISTER,,BUFFER SIZE

DTEOST==406	;LINE# TO START OUTPUT ON (SET OUTPUT DONE).  (SET BY 10, SETOMED BY 11)

	;407 NOT USED

DTETYI==410	;TELETYPE INPUT
		;LH=LINE#, RH=CHAR RECEIVED.  (SET BY 11, SETOM'ED BY 10)

DTEODN==411	;TELETYPE OUTPUT DONE
		;LH=LINE#, RH=BUFFER SIZE.  (SET BY 11, SETOM'ED BY 10)

DTEHNG==412	;HANGUP/DIALIN WORD  (SET BY 11, SETOM'ED BY 10)
		;0000NN - LINE # NN HUNG UP
		;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES)

;^ ADD MORE HERE, NOT TO EXCEED LOCATION 437
;.IFNZ DTE20P

;IOELEVEN RESIDES IN THE BOTTOM 14K OF THE CONSOLE PDP11, ALONG WITH 11DDT.
;I.E. LOCATIONS 0-70000.  BE SURE TO USE .;11DDT 14K VERSION OF DDT.
;THE UPPER 14K CONTAIN KLDCP.  THE FOLLOWING CALLS TO KLDCP ARE USED.
;THEY RETURN WITH C-BIT SET IF THEY LOSE (MICROCODE HUNG).

;NOTE: KLDCP ENJOYS CLOBBERING REGISTER 0 (A).  I DON'T
;KNOW IF ALL THESE CALLS DO, BUT WE'LL ASSUME THAT THEY DO.

TENSW=EMT!145	;UPDATE LOCATION DTESWR FROM THE SWITCHES

EXAM=EMT!103	;EXAMINE PDP10 MEMORY
 ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 BYTES CONTAINING PDP10 ADDRESS (LOW BITS FIRST)
 ;AFTER CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS (LOW BITS FIRST)

EXAMT=EMT!104	;EXAMINE PDP10 MEMORY
 ;.WORD PDP10-ADDRESS
 ;.WORD ADDRESS OF 3-WORD DATA BLOCK

DPOS=EMT!105	;DEPOSIT PDP10 MEMORY
 ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS
 ;AND REGISTER B HAS ADDRESS OF 3 BYTES CONTAINING ADDRESS

DPOST=EMT!106	;DEPOSIT PDP10 MEMORY
 ;.WORD PDP10-ADDRESS
 ;.WORD ADDRESS OF 3-WORD DATA BLOCK

D10MON=EMT!111	;DEPOSIT PDP10 MEMORY, -1
 ;.WORD PDP10-ADDRESS

$PMSG=EMT!25	;PRINT MESSAGE ON TTY
 ;.WORD ADDRESS OF ASCIZ MESSAGE

$CNTLC=100004	;JUMP HERE TO "CONTROL C" BACK TO KLDCP

;WHEN KLDCP IS IDLE, AND IN "ITS MODE", IT DOES JSR PC,3000
;WHICH CALLS IOELEVEN'S MAIN PROGRAM.  RETURN WITH "C" SET
;TO READ AND EXECUTE ONE KLDCP COMMAND LINE.  RETURN WITH "C"
;CLEAR TO PRINT KL10 HALTED OR CLOCK ERROR STOP MESSAGE.
;LOCATIONS 3004, 3006 MUST CONTAIN .RAD50/IOELEV/
;IOELEV WILL RUN ON KLDCP'S STACK.
;.IFNZ DTE20P
;INFORMATION ABOUT THE DTE20.
;EXCEPT FOR BYTE TRANSFER, WE USE THE TIME-TESTED SUBROUTINES PROVIDED BY KLDCP.

;THE INTERRUPT VECTOR IS AT 774, BUT WE CAN'T USE IT BECAUSE WOULD HAVE
;TO COORDINATE THINGS WITH KLDCP, WHICH IS OBVIOUSLY IMPOSSIBLE.

DLYCNT=174400	;2.6-2.7 UNIBUS ADDRESS EXTENSION FOR BYTE TRANSFER DMA
		;1.1-2.5 14-BIT 2'S COMPLEMENT OF NUMBER OF HALF-MICROSECONDS
		;	 TO DELAY BETWEEN PI0 INTERRUPTS IN BYTE TRANSFER

TO10AD=174420	;ADDRESS (WORD OR BYTE) OF TO-10 BYTE TRANSFER DATA

TO10BC=174414	;1.1-2.3 NEGATIVE BYTE COUNT, 2.7 LAST XFER
		;NORMALLY SET BY 10 WITH DATAO DTE,
		;TO10 XFER STARTS WHEN BOTH TO10AD AND TO10BC HAVE BEEN LOADED

TO11AD=174422	;ADDRESS (WORD OR BYTE) OF TO-11 BYTE TRANSFER DATA

TO11BC=174416	;1.1-2.3 NEGATIVE BYTE COUNT FOR TO-11 BYTE TRANSFER
		;2.5=1 => TO-11 TRANSFER IS 8-BIT BYTES, =0 => 16-BIT WORDS
		;2.6=1 => "ASCIZ" MODE (WHICH WE DON'T USE, OF COURSE)
		;2.7=1 => LAST XFER, UPON COMPLETION INTERRUPT BOTH 10 AND 11
		;   =0 => ONLY INTERRUPT 11.  11 CAN CHANGE TO11AD, TO11BC, CONTINUE.
		;TO11 XFER STARTS WHEN BOTH TO11AD AND TO11BC HAVE BEEN LOADED
		;THE TRANSFER HAPPENS USING DMA (NPR) IN 11, PI LEVEL 0 IN 10.

STATUS=174434	;DTE20 STATUS REGISTER
  ;READS:
 %STDNI==100000	;2.7 TO10 XFER DONE WITHOUT ERROR
 %STERI==20000	;2.5 TO10 XFER ABORTED BY ERROR
		;2.4 DATA OUT OF DTE RAM IS ALL ZERO (MAINT)
 %STINV==4000	;2.3 PDP10 IS INTERRUPTING PDP11
		;2.2 DEPOST OR EXAMINE WORD ONE (MAINT)
 		;2.1 PDP11 MEMORY PARITY ERROR IN TO10 XFER
		;1.9 PDP11 IS INTERRUPTING PDP10
 %STDNO==200	;1.8 TO11 XFER DONE WITHOUT ERROR
		;1.7 E BUFFER SELECT (MAINT)
 		;1.6 TO11 XFER STOPPED DUE TO ZERO BYTE (IN ASCIZ MODE)
		;1.5 TO11 XFER OR PDP10 EXAMINE ENCOUNTERED EBUS PARITY ERROR
		;1.4 1 => RESTRICTED MODE
		;1.3 0 => EXAMINE/DEPOSIT IN PROGRESS, 1 => DONE
 %STERO==2	;1.2 TO11 XFER ABORTED BY ERROR
		;1.1 1 => DTE ENABLED TO INTERRUPT PDP11
  ;WRITES:
 %STCLI==51000	;2.6+2.4+2.1 CLEAR TO10 XFER DONE AND ERROR FLAGS
 %STUNV==2000	;2.2 CLEAR PDP10 INTERRUPTING PDP11
 %STINX==400	;1.9 SET PDP11 INTERRUPTING PDP10
 %STCLO==121	;1.7+1.5+1.1 CLEAR TO11 XFER DONE AND ERROR FLAGS
		;1.6 ENABLE INTERRUPTS
		;1.4 DISABLE INTERRUPTS

DIAG1=174430	;DIAGNOSTIC WORD 1, INCLUDES FLAGS
 %D1ERR==4000	;2.3 KL10 CLOCK ERROR STOP
 %D1RUN==2000	;2.2 KL10 RUN INDICATOR (1 IF 11 WANTS 10 TO RUN)
 %D1HLT==1000	;2.1 KL10 HALT INDICATOR (1 IF 10 DOES A JRST 4)

DIAG3=174436	;DIAGNOSTIC WORD 3, INCLUDES FLAGS
 %D3BYT==1	;1.1 WRITING 0 SETS TO10 XFER IN WORD MODE, 1 BYTE MODE
		;THERE'S NOTHING ELSE OF THE SLIGHTEST USE IN THIS REGISTER,
		;SO IT'S OK TO WRITE IT AT ANY TIME.
.ENDC ;DTE20P

	.SBTTL LOW CORE

.IFZ DTE20P		;IF USING DTE20, THESE ARE SET UP BY KLDCP
.=4
	TRAP4
	340
	TRAP10
	340
;	TRAP14		;SET UP BY 11DDT
;	340
.=20
	TRAP10	;IOT
	340
	PWRFAL
	340
	TRAP10	;EMT
	340
	TRAP10	;TRAP
	340
.ENDC ;DTE20P

;CHAOS NET INTERRUPT VECTORS ARE UNFORTUNATELY NOT IN A REASONABLE ARRAY
.IFGE CHAOSP-1
.=270
	.WORD CHS0BK,5_5
	;274 IS INTERVAL TIMER
.ENDC ;CHAOSP-1
.IFGE CHAOSP-2
.=230
	.WORD CHS1BK,5_5
	;234 IS INTERVAL TIMER
.ENDC ;CHAOSP-2
.IFGE CHAOSP-3
.=240
	.WORD CHS2BK,5_5
	;244 IS INTERVAL TIMER	
.ENDC ;CHAOSP-3
.IFGE CHAOSP-4
	.ERROR WHERE DOES THE FOURTH CHAOSNET INTERRUPT VECTOR GO?
.ENDC ;CHAOSP-4

.IFNZ ETHERP
.=400
	ETHOBK
	5_5
	ETHIBK
	5_5
	ETHOBK	;COLLISION
	5_5
.ENDC ;ETHERP

.IFNZ T300P
.=254
	DSKBRK
	240	;BR5
.ENDC ;T300P

.=300
.REPT NDMS	;DM11s go in floating vectors
CONC DM,\.RPCNT+1,BRK
	240	;INTERRUPTS ON BR4 BUT WE MASK TO BR5 ANYWAY
.ENDR ;NDMS

.IFNZ NDLS
.=60
	DL1IBK	;FIRST DL11 LINE IS PDP11'S CONSOLE TTY, DIFFERENT ADDRESS
	240	;AGAIN INTERRUPTS ON BR4 BUT MASK TO BR5 SO CAN USE DH11 ROUTINES W/O FEAR
	DL1OBK
	240
.ENDC ;NDLS
.=310	
.REPT NDLS-1	;DL11S AFTER THE FIRST ARE IN FLOATING VECTORS
CONC DL,\.RPCNT+2,IBK
	240
CONC DL,\.RPCNT+2,OBK
	240
.ENDR

.=DHIBAS	;DON'T RELY ON RANDOM FLOATING VECTOR TO
		;COME OUT RIGHT, E.G. IF THERE IS A DL11
		;THERE WHICH WE AREN'T USING.
.REPT NDHS		;DH11S ARE IN FLOATING VECTOR AFTER DL11[E]S
CONC DH,\.RPCNT+1,IBK	;DH11 #n RECEIVE
	240
CONC DH,\.RPCNT+1,OBK	;DH11 #n TRANSMIT & ERROR
	240
.ENDR ;NDHS
.=100
	CLKBRK	;KW11-L 60-CYCLE CLOCK
	300	;ON BR6

.IFNZ GOULDP
.=174
	GLPBRK
	300	;BR5 BUT NEED TO LOCK OUT CLOCK SO MASK 6
.ENDC ;GOULDP

.IFG NMPTYS
.=56
MPXENB::0	;NONZERO TO ENABLE MULTISCHLUNKER
.ENDC

.IFZ DTE20P	;IF DTE20, KLDCP SUPPLIES THE STACK
.=1000
STKBAS::
	JMP INIT		;START AT 1000 IS CONVENTIONAL
.IFF ;DTE20P
.=3000		;ENTRY VECTOR
	JMP @#INIT
SADR=.-2		;ARG OF THE JMP@# IS CHANGED AFTER INITIALIZATION
	.RAD50 /IOELEV/
.ENDC ;DTE20P

	.SBTTL TEN-11 CHAOSNET COMMUNICATION AREA

.IFNZ TEN11P
T11BFL==8+<2*PKTMXW>		;BYTE LENGTH OF A PACKET BUFFER
				;FIRST 8 BYTES ARE BUFFER-FULL FLAG AND CKSM
.IIF NE T11BFL-<<T11BFL/4>*4>, .ERROR T11BFL NOT MULTIPLE OF 4

.IIF NE .-1004, .ERROR CHAOSNET TEN-11 COMMUNICATION AREA NOT AT RIGHT ADDRESS

;THIS AREA IS SHARED WITH THE PDP10 VIA TEN-11 INTERFACE.

	.WORD "CH,1	;ERROR CHECK AND VERSION NUMBER
T11I10:	.WORD 0,0	;SET NON-ZERO BY 11 TO REINITIALIZE 10
T11I11:	.WORD 0,0	;SET NON-ZERO BY 10 TO REINITIALIZE 11
	.WORD T11BFL,NT11BF	;BUFFER SIZE, NUMBER OF BUFFERS
	.BLKW 8		;SPARE WORDS
T11OBF:	.BLKB T11BFL*NT11BF	;TO-10 BUFFERS
 T11OBE==.	;END OF TO-10 BUFFERS
T11IBF:	.BLKB T11BFL*NT11BF	;FROM-10 BUFFERS
 T11IBE==.	;END OF FROM-10 BUFFERS
;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR
;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE.
;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS
;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW,
; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED
; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT.
;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0.
.ENDC ;TEN11P

	.SBTTL CONFIGURATION

; TABLES INDEXED BY H (PER HARDWARE UNIT)

.MACRO DHTE AD		;DH11 REGISTER ADDRESS GENERATOR
.REPT NDHS
 <AD>+<20*.RPCNT>
.ENDR
.ENDM

.MACRO DLTE AD		;DL11 REGISTER ADDRESS GENERATOR, FIRST IS WIERD
.IFNZ NDLS
	177560+<<AD>&7>
.REPT NDLS-1
	<AD>+<10*.RPCNT>
.ENDR
.ENDC ;NDLS
.ENDM

.MACRO DMTE AD	;DM11 register address generator
  .REPT NDMS
    <AD>+<10*.RPCNT>	;a DM11 eats 8 locations
  .ENDR
.ENDM

DMCSR:	DMTE 170500	;first DM11 is at 170500

DMLSR:	DMTE 170502	;selected line status at 170502

DHSCR:	DHTE DHCBAS	;SYSTEM CONTROL REGISTER
			;1.1-1.4 LINE NUMBER
			;1.5-1.6 MEMORY ADDRESS EXTENSION
 DHRENB==100		;1.7 RECEIVER INTERRUPT ENABLE
			;1.8 RECEIVER INTERRUPT
			;1.9 CLEAR NXM FLAG
			;2.1 MAINTENANCE MODE
 DHSNXM==2000		;2.2 NXM FLAG (GENERATES XMT INTERRUPT)
			;2.3 MASTER CLEAR
 DHSENB==10000		;2.4 STORAGE SILO FULL INTERRUPT ENABLE
 DHTENB==20000		;2.5 TRANSMITTER & NXM INTERRUPT ENABLE
			;2.6 STOARGE FULL INTERRUPT
 DHTDON==100000		;2.7 TRANSMITTER DONE INTERRUPT

DLKS==DHSCR
	DLTE 175610	;KEYBOARD STATUS REGISTER
			;1.1 PAPER TAPE READER ENABLE (WO)
			;1.2 DATA TERMINAL READY (RW)
			;1.3 REQUEST TO SEND (RW)
			;1.4 SECONDARY TRANSMIT DATA [OR MAKE BUSY] (RW)
			;1.5 UNUSED
			;1.6 DATASET INTERRUPT ENABLE (RW)
			;1.7 RECEIVE INTERRUPT ENABLE (RW)
			;1.8 RECEIVE DATA READY (RO)
			;1.9 UNUSED
			;2.1 UNUSED
			;2.2 SECONDARY RECEIVE DATA (RO)
			;2.3 RECEIVE ACTIVE (RO)
			;2.4 CARRIER DETECT (RO)
			;2.5 CLEAR TO SEND (RO)
			;2.6 RING INDICATOR (RO)
			;2.7 DATASET STATUS CHANGE (RO)

DHNRC:	DHTE DHCBAS+2	;NEXT RECEIVED CHARACTER
			;1.1-1.8 THE CHARACTER
			;1.9-2.3 LINE NUMBER
 %DXPAR==10000		;2.4 CHAR HAS WRONG PARITY
 %DXBRK==20000		;2.5 FRAMING ERROR (BREAK)
 %DXOVR==40000		;2.6 OVERRUN, PREVIOUS CHARS LOST
			;2.7 1 => THIS WORD VALID
DLKB==DHNRC
	DLTE 175612	;KEYBOARD INPUT REGISTER
			;1.1-1.8 RECEIVED DATA
			;2.4 PARITY ERROR (RO)
			;2.5 FRAMING ERROR (RO)
			;2.6 OVERRUN (RO)
			;2.7 OR OF ERROR BITS (RO)

DHLPR:	DHTE DHCBAS+4	;LINE PARAMETER REGISTER
			;1.1-1.2 CHARACTER LENGTH 0=5, 1=6, 2=7, 3=8 (PARITY BIT EXTRA)
			;1.3 1 => EXTRA STOP BIT
			;1.5 ENABLE PARITY
			;1.6 0 -> EVEN PARITY, 1 => ODD
			;1.7-2.1 RECEIVER SPEED
			; 0 OFF, 1 50, 2 75, 3 110, 4 134.5, 5 150, 6 200, 7 300
			; 10 600, 11 1200, 12 1800, 13 2400, 14 4800, 15 9600, 16 A, 17 B
			;2.2-2.5 TRANSMITTER SPEED, SAME CODES AS RECEIVER
			;2.6 HALF DUPLEX
			;2.7 ECHOPLEX

DHCA:	DHTE DHCBAS+6	;CURRENT ADDRESS
DLCA==DHCA
	.IREPT NDLS,0

DHBC:	DHTE DHCBAS+10	;BYTE COUNT (MINUS)
DLBC==DHBC
	.IREPT NDLS,0	;POSITIVE FOR DLS

DHBAR:	DHTE DHCBAS+12	;BUFFER ACTIVE REGISTER
			;BIT = 1 IF XMT ACTIVE ON CORRESP LINE, NUMBERED RIGHT TO LEFT
DLPS==DHBAR
	DLTE 175614	;PRINTER STATUS
			;1.1 SEND BREAK (RW)
			;1.3 LOOP BACK (RW)
			;1.6 INTERRUPT ENABLE (RW)
			;1.7 TRANSMITTER READY (RO)

DHBCR:	DHTE DHCBAS+14	;BREAK CONTROL REGISTER
			;BIT = 1 => SEND BREAK ON CORRESP LINE, NUMBERED RIGHT TO LEFT
DLPB==DHBCR
	DLTE 175616	;PRINTER BUFFER
			;1.1-1.8 DATA TO TRANSMIT

DHSSR:	DHTE DHCBAS+16	;SILO STATUS REGISTER
			;1.1-1.6 SILO ALARM LEVEL
			;1.7-1.8 READ EXTENDED ADDRESS (R.O.)
			;1.9-2.5 SILO FILL LEVEL (R.O.)
			;2.7 MAINTENANCE PATTERN (W.O.)

DHOAC:	.IREPT NDHS,0	;BIT ON IF SOFTWARE THINKS LINE'S TRANSMITTER IS ACTIVE
DLOAC==DHOAC
	.IREPT NDLS,0	;NON-ZERO IF LINE'S TRANSMITTER IS ACTIVE

DHTYNO:	.IREPT NDHS, NFDHTY+<32.*.RPCNT>	;TTY INDEX OF FIRST LINE ON THIS DH11
DLTYNO==DHTYNO
.IIF NZ CTYP,0		;TTY INDEX OF LINE ON THIS DL11
.IREPT NDLS-CTYP,NFDLTY+<2*.RPCNT>

STROUT:	.IREPT NDHS, STRDH	;OUTPUT-START ROUTINES
	.IREPT NDLS, STRDL
.IIF NZ NMPTYS, STRMPK

	.BLKB NFTTY	;AVOID LABEL OVERLAPPAGE

;TABLES INDEXED BY I (PER LINE)

T HDWR:			;HARDWARE UNIT INDEX, GOES IN H
.IIF NZ CTYP, NFDLHX
	.REPT NDHS
	 ZZ==.RPCNT*2
	 .REPT 16.
	  ZZ		;16 LINES ON EACH DH-11
	 .ENDR
	.ENDR
	.=.-<2*NDHUN>
.IREPT NDLS-CTYP,NFDLHX+<2*.RPCNT>+<2*CTYP>
.IREPT NMPTYS,	MPKHWR		;MULTIPLEXOR-KLUDGE TTYS

T DHLSEL:		;DH11 LINE SELECT WORDS
.IIF NZ CTYP,	0		;NONE FOR CTY
	.REPT NDHS
	 .REPT 16.
	  DHTENB+DHRENB+.RPCNT
	 .ENDR
	.ENDR

T DHLBIT:		;BIT CORRESPONDING TO THIS LINE IN DHBAR, ETC.
.IIF NZ CTYP,	0		;NONE FOR CTY
	.REPT NDHS
	 .REPT 16.
	  1_.RPCNT
	 .ENDR
	.ENDR

T BUFPNT:		;BUFFER POINTERS
	.IREPT NCT, BUFFRS+<.RPCNT*MAXBSZ>

T BUFSIZ:		;BUFFER SIZES (I.E. AMOUNT TO USE AT CURRENT SPEED)
	.REPT NCT
	 0		;SET DURING INITIALIZATION
	.ENDR

T NRMIPC:		;NORMAL INPUT CHARACTER PROCESSING ROUTINES
.IIF NZ CTYP, RCV	;CTY NORMAL INPUT
	.REPT 16.*NDHS
	 DHNRMI		;DH11 TTY NORMAL INPUT
	.ENDR
	.=.-<2*NDHUN>
.IREPT NDLS-CTYP,RCV	;DL11 NORMAL INPUT
.IREPT NMPTYS,	RCV	;NORMAL INPUT FOR TTYS ON MULTIPLEXOR-KLUDGE
.IIF NE .-NRMIPC-NLTTY, .ERROR BARF AT NRMIPC
.IFNZ NMPTYS
	.=NRMIPC+MPXIDX
	MPXINP		;INPUT FROM THE MULTIPLEXED LINE IS SPECIAL
	.=NRMIPC+NLTTY
.ENDC

T TTYIPC:		;CURRENT INPUT CHAR PROCESSING ROUTINES
	.BLKW NCT	;SET UP AT INIT TIME
.IIF NE .-TTYIPC-NLTTY, .ERROR BARF AT TTYIPC

T AUTOSP:		;IF NON-ZERO, LINE GOES INTO AUTOSPEED WHEN DIALED UP
	.REPT NCT	;IF MINUS ALSO WHEN BREAK SEEN
	 ZZ===.
	 ASPIRP ^\
	  .IIF EQ .RPCNT+<NFTTY/2>-N,+1	;THIS LINE AUTOSPEED ON DIALUP
	  .IIF EQ .RPCNT+<NFTTY/2>+N,-1	;ALSO ON BREAK
	  \
	 .IIF EQ .-ZZ, 0	;THIS LINE NOT AUTOSPEED
	.ENDR
.IIF NE .-AUTOSP-NLTTY, .ERROR BARF AT AUTOSP

.IFM MC
M2LMAP:			;MAP FROM DM11-BB CHANNEL NUMBERS TO TTY INDICES
	2*1		;0 T01
	0		;1 NONE
	0		;2 NONE
	2*4		;3 T04
	2*5		;4 T05
	2*6		;5 T06
	2*7		;6 T07
	2*10		;7 T10
	2*11		;10 T11
	2*12		;11 T12
	2*13		;12 T13
	2*14		;13 T14
	2*15		;14 T15
	2*16		;15 T16
	2*17		;16 T17
	0		;17 NONE
	2*21		;20 T21
	2*22		;21 T22
	2*23		;22 T23
	2*24		;23 T24
	2*25		;24 T25
	2*26		;25 T26
	2*27		;26 T27
	2*30		;27 T30
	2*31		;30 T31
	2*32		;31 T32
	2*33		;32 T33
	2*34		;33 T34
	2*35		;34 T35
	2*36		;35 T36
	2*37		;36 T37
	2*40		;37 T40
.ENDC ;MC

.IIF NE NDMS, .IIF NE .-M2LMAP-<40*NDMS>, .ERROR Too few M2LMAP entries for DM11s.

.IFNZ NDMS

T DIALED:		;0 IF LINE NOT DIALED UP (OR NO MODEM CONTROL ON THIS LINE)
	.REPT NCT	;+ IF DIALED UP (CLEAR TO SEND IS ON)
	 0		;- IF CLEAR TO SEND DROPPED, INC EACH TICK, REACHES 0 => HUNG UP
	.ENDR

.ENDC ;NDMS

T TTYHNG:		;DIALUP/HANGUP STATUS WAITING TO BE SENT TO 10 (0 IF NONE)
	.REPT NCT
	0
	.ENDR

T TYPING:		;POSITIVE IF LINE IS TYPING OUT FOR 10
	.REPT NCT	; WHICH MEANS -10 SHOULD BE INFORMED WHEN TYPEOUT IS FINISHED
	 0		;0 FOR NO -10 TYPEOUT, MINUS TO SEND <CALL> AFTER TYPEOUT
	.ENDR

;MISC VARIABLES

DLXOFF:	-1		;NON-ZERO IF DL10 PORT TURNED OFF BY 10
NO.ITS:	-1		;NON-ZERO IF HAVEN'T ESTABLISHED COMMUNICATION WITH ITS YET
VERSN:	.BYTE NFTTY/2,NCT	;I/O VERSION NUMBER
DMINI:	0		;NON-ZERO => MODEM SCANNER JUST TURNED ON, GETTING INITIAL STS
WAKE:	0		;CLOCK INTERRUPT WAKE UP MAIN PROGRAM FLAG
HNGSIG:	0		;NUMBER OF NON-ZERO TTYHNG WORDS
10RQ:	0		;LIGHT HACKS
LITHSE:	7
.IFNZ DTE20P
CLKENB:	0		;KL10 WANTS 11 TO RELAY CLOCK INTERRUPTS
KLDCPF:	0		;NON-ZERO => USER WANTS TO GIVE A COMMAND TO KLDCP
DDTMOD:	0		;NON-ZERO => DDT MODE TTY INPUT
DDTCHR:	-1		;NON-NEGATIVE => CHAR TYPED FOR DDT
CURSWR:	52525		;LAST SWITCHES SENT TO -10
OUTCMD:	0		;0 IF OUTPUT TRANSFER IDLE
			;ELSE CURRENT COMMAND / 400
OUTSVI:	-1		;LINE# OF CURRENT OUTPUT TRANSFER
OUTSVC:	-1		;#BYTES OF CURRENT OUTPUT TRANSFER
INPCMD:	0		;0 IF INPUT TRANSFER IDLE
			;ELSE CURRENT COMMAND / 400
INPSVI:	-1		;LINE# OF CURRENT INPUT TRANSFER
INPSVC:	-1		;#BYTES OF CURRENT INPUT TRANSFER
.ENDC ;DTE20P
.IFNZ NMPTYS
MPXOAC:	0		;0 IDLE, -1 SENDING HEADER, 1 SENDING DATA
MPXOLN:	0		;2 x MPXK# OUTPUTTING FOR
MPXSEL:	NFMPTY		;TTY INDEX SELECTED FOR MPX INPUT
MPXPNT:	.IREPT NMPTYS,0	;POINTER TO CRUFT TO SEND TO EACH MPXED LINE
MPXNBT:	.IREPT NMPTYS,0	;# BYTES TO SEND, 0 IF IDLE
MPXHED:	.BYTE 0,0	;MPX OUTPUT HEADER: 200+MPXK#, BYTE COUNT
.ENDC ;NMPTYS

	.SBTTL CHAOSNET VARIABLES & TABLES

.IFNZ CHAOSP

NSUBNT==80.	;MAXIMUM CAPACITY 80. SUBNETS

.IFNZ DL10P	;DL10 UNSHARED
DLCRBN:	0	;CURRENT RECEIVE (11 to 10) BUFFER (0 OR 2)
DLCNXT:	.WORD 2,0	;FOR SWITCHING BUFFERS
DLCIBF:	.BLKW PKMAX	;DL10 INPUT BUFFER
.ENDC ;DL10P

.IFNZ TEN11P	;TEN11 UNSHARED
T11OBP:	T11OBF	;NEXT BUFFER TO 10
T11IBP:	T11IBF	;NEXT BUFFER FROM 10
T11IBA:	0	;NON-ZERO MEANS INPUT BUFFER ACTIVE, T11IBP NEEDS ADVANCING
		;THIS IS SEPARATE FROM CHISTS+CHXT11 FOR GOOD REASONS
T11CKE:	0	;COUNT OF TEN-11 CHECKSUM ERRORS
T11TIM:	0	;TIMEOUT ON TRANSMISSION OF PACKET TO 10
.ENDC ;TEN11P

.IFNZ ETHERP
ETHSBN==2	;SUBNET WHICH IS THE ETHERNET
.SEE ETHHSN	;MY HOST NUMBER BYTE (DEFINED IN MACHINE CONFIGURATION AREA)
ETHMXH==15.-1	;MAXIMUM NUMBER OF HOPS (-1 => BUG IN XEROX PROGRAMS)
ETHIBF:	.BLKW PKTMXW+1	;INPUT FROM ETHERNET BUFFERED HERE (+1 HARDWARE BUG?)
ETHHDW==PKHDW-2	;ALLOW FOR OVERLAP OF CHAOSNET HEADER AND 2-WORD ETHERNET HEADER
		;THIS IS THE OFFSET (IN WORDS) WHERE THE ETHERNET PACKET STARTS

;HERE IS A PACKET USED TO BUILD THE ETHERNET BROADCAST GATEWAY INFO.  WHAT A CROCK.
EGTBUF:	.BLKW PKHDW	;SPACE FOR CHAOSNET HEADER
EGTPLN:	0		;PUP LENGTH
	201		;PUP TYPE 201
EGTPID:	.WORD 0,0	;PUP IDENTIFIER
	0		;DESTINATION (BROADCAST)
	.WORD 0,2	;DEST SOCKET 2
EGTSRC:	.BYTE ETHHSN,ETHSBN	;SOURCE (ME)
	.WORD 0,2	;SOURCE SOCKET 2
EGTSBN:	;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST
	.BLKW 2*NSUBNT
	0		;PUP CHECKSUM

.IF DF NDVRBF
DVRHST:	0			;ZERO IF IDLE, OR FOREIGN HOST USING
DVRIDX:	0			;FOREIGN INDEX
DVRLIX:	0			;LOCAL INDEX (AOS EACH TIME)
DVRTIM:	0			;COUNTS UP TO IDLE THE FOREIGN HOST
DVRRTR:	0			;COUNTS UP FOR RETRANSMISSION

DVRBFL==2*<PKHDW+10.+<DATMAX/2>+1> ;NUMBER OF BYTES IN A DOVER BUFFER (HOLDS PUP IN CHAOSNET PACKET)
DVRBUF:	.BLKB DVRBFL*NDVRBF	;RING OF BUFFERS HERE
DVRBF2:	.BLKW PKHDW+2		;BUFFER FOR SENDING STS/OPN/CLS BACK (ALSO END OF RING)
DVRBFP:	DVRBUF			;POINTER TO NEXT BUFFER TO GO OUT TO DOVER
DVRMSK:	0			;MASK OF WHICH BUFFERS CONTAIN PACKETS (MSB = DVRBFP PKT)
 .IIF GT NDVRBF-16., .ERROR NDVRBF MAXIMUM OF 16. ALLOWED
DVRPKP:	0			;IF NON-ZERO, POINTER TO SPECIAL PACKET TO SEND
DVRID:	0			;ID FOR NEXT PACKET EXPECTED BY DOVER, THIS PACKET IS OR
				; WILL BE IN THE BUFFER DVRBFP POINTS AT
DVROFS:	0			;ID OFFSET, SUBTRACT FROM CHAOS ID TO GET PUP ID
NDVRFK:	0	;*** TEMPORARY KLUDGE ***
.ENDC ;NDVRBF
.ENDC ;ETHERP

PULSAR:	0	;COUNTS DOWN TO 0 THEN TRIGGERS TRANSMISSION OF A "TEST MESSAGE"
PULSON:	FTPULS	;IF THIS IS NON-ZERO, FEATURE IS ENABLED, VALUE IS TICKS BETWEEN PULSES
USECBL:	0	;IF NON-ZERO, 10 TALKING TO SELF STILL GOES THROUGH CABLE

NCHX==DL10P+TEN11P+CHAOSP+<2*ETHERP> ;NUMBER OF ENTRIES IN SOURCE AND SINK TABLES
.IIF DF NDVRBF, NCHX==NCHX+1

;METERS ETC.
.IFNZ FTGARB
CHSGBF:	.BLKW PKMAX	;HOLDS LAST PACKET THAT CAME IN WITH A CHECKSUM ERROR
CHSGBH:	0		;UNIBUS ADDRESS OF INTERFACE THAT ABOVE CAME IN ON
CHSGBS:	0		;STATUS REGISTER THAT GOES WITH ABOVE
CHSGBC:	0		;BIT COUNT THAT GOES WITH ABOVE
.ENDC ;FTGARB

;FOLLOWING HAVE SEPARATE ENTRIES FOR EACH CABLE
NPKSGB:	.IREPT CHAOSP+ETHERP,0	;COUNTS THE NUMBER OF PACKETS RECEIVED WITH CHECKSUM ERRORS
HPKSGB:	.IREPT CHAOSP+ETHERP,0	;HIGH-ORDER WORD OF COUNTER
NPKSRL:	.IREPT CHAOSP+ETHERP,0	;COUNTS THE NUMBER OF PACKETS RAM LOST,
			; I.E. DIDN'T COME IN WITH A CHECKSUM ERROR BUT AFTER
			; READING IT OUT HAD ONE.  EITHER THE PACKET WAS THE
			; WRONG LENGTH, OR THE RAM IS LOSING, OR HARDWARE
			; CLOBBERAGE.  FOR ETHERNET IS PUP CKSM ERR COUNT
			;THIS WORD ALSO IS WHERE BIT COUNT ERRORS WOULD END UP
HPKSRL:	.IREPT CHAOSP+ETHERP,0	;HIGH-ORDER WORD OF COUNTER
CHSRLH:	0		;UNIBUS ADDRESS OF INTERFACE THAT ABOVE LAST HAPPENED ON.
CHSRLC:	0		;RESIDUAL BIT COUNT FOR ABOVE
NPKSLS:	.IREPT CHAOSP,0	;NUMBER OF PACKETS LOST ACCORDING TO LOSS COUNT IN HARDWARE
HPKSLS:	.IREPT CHAOSP,0	;HIGH-ORDER WORD OF COUNTER
NPKSAB:	.IREPT CHAOSP+ETHERP,0	;NUMBER OF TRANSMISSIONS ABORTED (BY COLLISION OR RECEIVE-BUSY)
HPKSAB:	.IREPT CHAOSP+ETHERP,0	;HIGH-ORDER WORD OF COUNTER
NPKSI:	.IREPT NCHX,0	;TOTAL NUMBER OF PACKETS IN ON EACH SOURCE
HPKSI:	.IREPT NCHX,0	;HIGH-ORDER WORD OF COUNTER
NPKSO:	.IREPT NCHX,0	;TOTAL NUMBER OF PACKETS OUT ON EACH SINK
HPKSO:	.IREPT NCHX,0	;HIGH-ORDER WORD OF COUNTER
NPKSIG:	0		;NUMBER OF PACKETS IGNORED AT CHIFLS
NPKSBD:	.IREPT NCHX,0	;NUMBER OF PACKETS BAD AT CHSIHB
HPKSBD:	.IREPT NCHX,0	;HIGH-ORDER WORD OF COUNTER
NPKSRF:	0		;NUMBER OF PACKETS FOR WHICH ROUTING FAILED
RFSBNT:	-1		;2* SUBNET# OF LAST ROUTING FAILURE

;"INTERFACE ADDRESSES"
; A NEGATIVE INTERFACE ADDRESS IS THE UNIBUS ADDRESS OF A CHAOS INTERFACE.
; A ZERO INTERFACE ADDRESS MEANS THE DL10
; A POSITIVE INTERFACE ADDRESS MEANS THE TEN-11, VALUE BETTER BE OCTAL 1011.

CHSIBF:	.BLKW PKMAX*CHAOSP	;INPUT BUFFER FOR PACKETS IN FROM CHAOS HDWR

;THIS IS WHAT IS SENT BACK IN RESPONSE TO RFC TO "STATUS".
;FOR NOW, JUST THE NAME OF THE MACHINE.
HSTNAM:
.ENDC ;CHAOSP    ;FUCK A DOG, PALX!
.IFM MC-DL
	.ASCII \MC-IO/11\
.ENDC
.IFM AI
	.ASCII \AI-CHAOS-11\
.ENDC
.IFNZ CHAOSP     ;FUCK A DOG, PALX!
.IIF GE .-HSTNAM-32., .ERROR HSTNAM TOO LONG
.IREPT 32.-<.-HSTNAM>, .BYTE 0	;PAD ON THE RIGHT WITH 0'S

;CHAOSNET INPUT SOURCE AND OUTPUT SINK TABLES

	;NOTE WELL, THE CODE RELIES ON THE ORDER OF THESE INDICES
.IIF NZ DL10P, CHXDLC==0	;DL10 INDEX
.IIF NZ TEN11P, CHXT11==2*DL10P	;TEN11 INDEX
CHXCHS==2*<DL10P+TEN11P> ;FIRST CHAOS INDEX
.IIF NZ ETHERP, CHXETH==CHXCHS+<2*CHAOSP> ;ETHERNET INDEX
.IIF NZ ETHERP, CHXEGT==CHXETH+2	;ETHERNET GATEWAY-INFO-BROADCAST KLUDGE INDEX
.IIF DF NDVRBF, CHXDVR==CHXEGT+2	;DOVER PROTOCOL TRANSLATOR
.MACRO CHXCHK TAG
.IIF NE .-TAG-NCHX-NCHX, .ERROR TAG WRONG LENGTH TABLE
.ENDM CHXCHK

;CHAOSNET INPUT SOURCE TABLES

CHIBFP:		;BUFFER POINTER
.IIF NZ DL10P,	DLCIBF	;DL10 INPUT BUFFER
.IIF NZ TEN11P,	0	;CURRENT TEN11 INPUT BUFFER (SET FROM T11IBP+8)
.IREPT CHAOSP,	CHSIBF+<PKMAX*2*.RPCNT>	;CHAOS INPUT BUFFER
.IIF NZ ETHERP, ETHIBF	;ETHERNET
.IALSO		EGTBUF	;..
.IIF DF NDVRBF,	0	;CURRENT DOVER BUFFER, COULD BE CHAOS OR PUP
CHXCHK CHIBFP

CHIHDL:	.IREPT NCHX, 0	;LENGTH OF HEADER IN WORDS, PACKET CURRENTLY IN BFR

CHISTS:	.IREPT NCHX, 0	;STATUS (0 IDLE, +1 HAS INPUT, -1 BEING OUTPUT)

CHILNG:	.IREPT NCHX, 0	;LENGTH OF CONTAINED PACKET IN WORDS

CHIOUX:	.IREPT NCHX, 1	;DESTINATION OUTPUT SINK INDEX  (-1 IF DIRECTED TO PDP11 ITSELF)

CHICBA:	.IREPT NCHX, 0	;DESTINATION CABLE ADDRESS

CHIRFL:		;ADDRESS OF REFILL ROUTINE
.IIF NZ DL10P,	DLCRFL
.IIF NZ TEN11P,	T11RFL
.IREPT CHAOSP,	CHSRFL
.IIF NZ ETHERP, ETHRFL	;ETHERNET
.IALSO		CPOPJ	;..
.IIF DF NDVRBF,	DVRRFL
CHXCHK CHIRFL

CHIHWR:		;POINTER TO HARDWARE
.IIF NZ DL10P,	1	;NOT USED
.IIF NZ TEN11P,	3	;NOT USED
.IREPT CHAOSP,	CAICSR+<400*.RPCNT>	;QUAD-CHAOS INTERFACES HAVE TO BE 200 APART
.IIF NZ ETHERP, 164200			;AND WE MAKE IT 400 BECAUSE ETHERNET GETS IN WAY
.IALSO		5	;NOT USED
.IIF DF NDVRBF,	7	;NOT USED

;CHAOSNET OUTPUT SINK TABLES

CHOHWR==CHIHWR	;POINTER TO HARDWARE

CHOSTS:	.IREPT NCHX, 0	;STATUS (0 IDLE, +1 TRANSMITTING, -1 RETRANSMITTING
			; AFTER TRANS ABORT, +2 DELAYING AFTER TRANSMIT ABORT BEFORE RETRANSM)
CHOINX:	.IREPT NCHX, 1	;CURRENTLY-ACTIVE CHIxxx INDEX

CHOXMT:		;START TRANSMISSION ROUTINE
.IIF NZ DL10P,	DLCXMT
.IIF NZ TEN11P,	T11XMT
.IREPT CHAOSP,	CHSXMT
.IIF NZ ETHERP,	ETHXMT	;ETHERNET
.IALSO		1	;NOT USED (CHXEGT)
.IIF DF NDVRBF,	DVRPKT	;DOVER
CHXCHK CHOXMT

CHXSBN:		;SUBNET NUMBER +400 FOR STATUS SERVER
.IIF NZ DL10P, DLCADR/400+400
.IIF NZ TEN11P, T11ADR/400+400
.REPT CHAOSP
 CONC CHAD,\.RPCNT,/400+400
.ENDR ;CHAOSP
.IIF NZ ETHERP,	ETHSBN+400	;ETHERNET
.IALSO		776	;NOT REAL (ETHERNET GATEWAY)
.IIF DF NDVRBF,	777	;NOT REAL (DOVER)
CHXCHK CHXSBN

CHXRTF:	.IREPT NCHX, 0		;NON-ZERO MEANS BROADCAST ROUTING INFO TO THIS GUY

.IFNZ CHSBTB
CHSIDL:	.IREPT NCHX, 0		;NUMBER OF TICKS WAITING FOR TRANSMIT-DONE
CHSRST:	.IREPT NCHX, 0		;NUMBER OF TIMES HAD TO RESET HUNG INTERFACE
.ENDC ;CHSBTB

;;; SUBNET/ROUTING TABLES

;INDEX BY TWICE SUBNET NUMBER
SBNTYP:	.IREPT NSUBNT, 0	;TYPE OF CONNECTION TO THIS SUBNET:
				; 0 VIA GATEWAY, WITH AUTOMATIC ROUTING
				; -1 VIA GATEWAY, PATCHED IN BY HUMAN, DON'T CHANGE
				; 1 HARDWARE CONNECTION

SBNADR:				;ADDRESS OF CONNECTION TO THIS SUBNET
				;NETWORK ADDRESS IF SBNTYP NEGATIVE OR ZERO
				;INDEX IN SOURCE/SINK TABLES IF SBNTYP GREATER THAN ZERO
	0	;0  USED FOR UNKNOWN SUBNETS.  WHEN IN DOUBT, BROADCAST.
	0	;1  9TH FLOOR CABLE
	0	;2  (NOT CURRENTLY USED)
	440	;3  MC, ASSUME VIA MC-IO-11
	426	;4  AI, ASSUME VIA AI-CHAOS-11
	.IREPT NSUBNT-5, 0	; WHEN IN DOUBT, BROADCAST

SBNCST:	.IREPT NSUBNT, 1000	;COST OF ROUTING VIA CURRENT GATEWAY, SEE CHAORD

;NOW FILL IN TABLES FOR HARDWARE CONNECTIONS THAT EXIST ON THIS MACHINE
;INCLUDING TRANSFINITE HAIR FOR ETHERNET GATEWAY INFO PACKET
ZZ==.
.IFNZ DL10P
DLCSBN==DLCADR/400	;SUBNET PDP10 ON OTHER END OF DL10 IS ON
.=SBNTYP+<DLCSBN*2>
	1
.=SBNADR+<DLCSBN*2>
	CHXDLC
.=SBNCST+<DLCSBN*2>
	10.		;DIRECT 10/11 CONNECTION COSTS 10.
.ENDC ;DL10P
.IFNZ TEN11P
T11SBN==T11ADR/400	;SUBNET PDP10 ON OTHER END OF TEN11 IS ON
.=SBNTYP+<T11SBN*2>
	1
.=SBNADR+<T11SBN*2>
	CHXT11
.=SBNCST+<T11SBN*2>
	10.		;DIRECT 10/11 CONNECTION COSTS 10.
.ENDC ;TEN11P
.ENDC ;CHAOSP

.IFM MC-DL
	  CBLCST=11.		;CABLE CONNECTION COSTS 11.
.ENDC
.IFM AI
	  CBLCST=22.		;AI COSTS MORE 'CAUSE IT'S SICK
.ENDC

.IFNZ CHAOSP		;sweet fucking jesus, palx
;HAIR FOR MULTIPLE CABLE INTERFACES
.REPT CHAOSP
  CONC IZZZ==CHAD,\.RPCNT
  IZZ==<IZZZ/400>*2
  .=SBNTYP+IZZ
	  1
  .=SBNADR+IZZ
	  CHXCHS+<.RPCNT*2>
  .=SBNCST+IZZ
	  CBLCST		;THE CABLE COST
.ENDR ;CHAOSP

.IFNZ ETHERP
.=SBNTYP+<ETHSBN*2>
	1
.=SBNADR+<ETHSBN*2>
	CHXETH
.=SBNCST+<ETHSBN*2>
	11.
.ENDC ;ETHERP

.=ZZ

;;; CLOCKS
4SEC:	0		;4-SECOND CLOCK COUNTER
15SEC:	0		;15-SECOND CLOCK COUNTER

.ENDC ;CHAOSP

;PATCH AREA

PAT: PATCH: .BLKW 100

	.SBTTL RING BUFFERS

.MACRO RING SIZE
	99$		;IN-POINTER
	99$		;OUT-POINTER
	0		;NUMBER OF WORDS IN RING
	<SIZE>		;MAX NUMBER ALLOWED
	<2*<SIZE>>+99$	;MAX ADDRESS ALLOWED
	99$		;MIN ADDRESS ALLOWED
99$:	.BLKW <SIZE>	;BUFFER
.ENDM

RINGIN==0
RINGOT==2
RINGCT==4
RINGSZ==6
RINGTP==10
RINGBT==12
RINGBF==14

; DEFINE THE RING BUFFERS

TYORNG:	RING <NCT*2>	;OUTPUT-DONE RING, CONTENTS = LINE NUMBER PDP10 STYLE
			;HAS TO BE EXTRA BIG BECAUSE THE OUTPUT DONES PUT IN ON
			;STARTUP FILL IT UP, THEN SOMETIMES ITS PUTS ONE IN
			;BEFORE IT TAKES ANY OUT.

TYIRSZ==NCT*20		;8 CHARS PER TTY (2 WORDS PER CHAR)
TYIRNG:	RING TYIRSZ	;TTY INPUT RING, FIRST WORD IS CHARACTER, SECOND LINE NUMBER



;MOV #RING,B
;MOV WORD,A
;CALL PUT

PUT:	CMP RINGCT(B),RINGSZ(B)
	BLT 1$
	 BPT		;BLOATED
1$:	PUSH C
	MOV RINGIN(B),C
	MOV A,(C)+
	CMP C,RINGTP(B)
	BLO 2$
	 MOV RINGBT(B),C
2$:	MOV C,RINGIN(B)
	POP C
	INC RINGCT(B)
	RET

;MOV #RING,B
;CALL GET
;WORD RETURNED IN A
; IT IS AN ERROR TO CALL THIS IF RING IS EMPTY

GET:	TST RINGCT(B)
	BGT 1$
	 BPT		;EMPTY
1$:	PUSH C
	MOV RINGOT(B),C
	MOV (C)+,A
	CMP C,RINGTP(B)
	BLO 2$
	 MOV RINGBT(B),C
2$:	MOV C,RINGOT(B)
	POP C
	DEC RINGCT(B)
	RET

CLRING:	CLR RINGCT(B)		;CLEAR A RING
	MOV RINGBT(B),RINGIN(B)
	MOV RINGBT(B),RINGOT(B)
	RET
.IFNZ DTE20P
	.SBTTL DTE20 SUBROUTINES

;THE DTE20 MUST NOT BE HACKED AT INTERRUPT LEVEL, BECAUSE KLDCP USES IT TOO.
;THE FOLLOWING THREE LOCATIONS ARE ARGS TO/FROM THE FOLLOWING TWO SUBROUTINES.

LH:	0	;LOW 16 BITS OF LEFT HALF
RH:	0	;LOW 16 BITS OF RIGHT HALF
SNB:	0	;SIGN BIT (0 IF +, NON-0 IF -)

;JSR B,HWEXAM
; .WORD ADDR
;EXAMINE PDP10 LOC, SPLIT INTO HALFWORDS, SET LH, RH, SNB
;RETURNS WITH "Z" SET IF LOCATION HAS POSITIVE SIGN, "Z" CLEAR IF MINUS SIGN

HWEXAM:	PUSH <A,C>	;SAVE REGS
	PUSH <#0,(B)+>	;PUT PDP10 ADDRESS ONTO PDL
	MOV SP,A	;SET UP POINTER TO ADDRESS
	EXAM		;EXAMINE LOCATION, SET A TO POINT TO 3-WORD RESULT BUFFER
	 BCS UHUNG	;BRANCH IF UCODE HUNG
	MOV (A)+,RH	;LOW 16 BITS => RH
	MOV (A)+,C	;PICK UP MIDDLE 16 BITS
	MOV (A)+,A	;PICK UP HIGH 4 BITS
	ROR A		;LSHC <A,C>,-2 TO GET PDP10 LH INTO C
	ROR C
	ROR A
	ROR C	
	MOV C,LH
	BIC #177775,A	;LEAVE SIGN BIT IN 1.2 OF A
	MOV A,SNB
	ADD #4,SP	;POP ADDRESS OFF PDL
	POP <C,A>	;RESTORE REGS
	TST SNB
	RTS B		;RETURN SKIPPING IN-LINE PARAMETER

;JSR B,HWDEP
; .WORD ADDR
;ASSEMBLE LH, RH, SNB INTO PDP10 AND DEPOSIT IN ADDR

HWDEP:	PUSH <A,B,C>
	MOV LH,C
	CLR A
	TST SNB
	BEQ 1$
	MOV #2,A
1$:	ASL C
	ROL A
	ASL C
	ROL A
	PUSH <A,C,RH>	;PUSH HIGH, MIDDLE, AND LOW BITS
	MOV SP,A	;POINTER TO DATA
	PUSH <#0,(B)>	;PUSH HIGH AND LOW ADDRESS
	MOV SP,B	;POINTER TO ADDRESS
	DPOS		;DO THE DEPOSIT
	 BCS UHUNG	;BRANCH IF UCODE HUNG
	ADD #10.,SP	;POP ADDRESS AND DATA OFF PDL
	POP <C,B,A>
	TST (B)+	;SKIP TRAILING PARAMETER
	RTS B

UHUNG:	$PMSG
	 .WORD 1$
	SETOM NO.ITS	;GIVING UP	
	JMP $CNTLC

1$:	.ASCIZ/?MICROCODE HUNG/

.ENDC ;DTE20P
.IFNZ DL10P
	.SBTTL MAIN LOOP FOR DL10

MAIN:
.IIF NZ TEN11P, CALL T11WAK	;CHECK UP ON TEN-11 INTERFACE
.IFNZ ETHERP
	TST CHXRTF+CHXETH	;NEED TO BROADCAST ROUTING INFO TO ETHERNET?
	BEQ 666$
	CALL ETHRUT
666$:
.ENDC ;ETHERP
	BIT #DLXPRT,DLXCSR	;PORT TO 10 ENABLED?
	BNE 1$			;YES
	SETOM NO.ITS		;NO, FLAG THERE IS NO ITS
	SETOM DLXOFF		;AND THAT WE THINK DL10 PORT IS OFF
	BR MAIN			;AND WAIT FOR IT TO TURN ON

1$:	TST DLXOFF		;DID DL10 JUST TURN ON?
	BEQ 4$			;NO, IT WAS ON BEFORE
	CLR DLXOFF		;YES, SO REMEMBER THAT
	MOV VERS,A		;CHECK VERSION SUPPLIED BY -10
	BEQ 2$			;ZERO OK (MUST BE SALVAGER)
	CMP A,VERSN
	BEQ 2$
	 BPT			;-10 AND -11 PROGRAMS NOT SAME CONFIG
2$:

4$:	BIT #DLXPAR+DLXNXM,DLXCSR	;ERROR ACCESSING MEMORY?
	BEQ 5$			;NO
	BPT			;DON'T GO OFF DESTROYING PEOPLE'S FILES

;WAIT FOR -10 TO REQUEST SERVICE, OR CLOCK TO TICK

5$:	CLR 10RQ
	BIT #DLX11I,DLXCSR	;10 REQUESTING SERVICE?
	BEQ 10$
	SETOM 10RQ
	BIS #DLXZ11,DLXCSR	;YES, CLEAR FLAG
	BR CHKOST		;AND GO CHECK FOR THINGS TO DO

10$:	TST WAKE		;NO, CHECK ANYWAY IF 60 CYCLE CLOCK HAS TICKED
	BEQ MAIN		;NEITHER, JUST WAIT
	CLR WAKE		;CLOCK HAS TICKED, CLEAR FLAG
	INC DLXUP		;AND INCREMENT COUNTER 10 IS SUPPOSED
	BEQ 11$			; TO SETOM EVERY 1/2 SEC
	CMP DLXUP,#15.*60.	;IF IT DOESN'T TOUCH IT FOR 15 SECONDS,
	BLE 12$			; CONSIDER IT DOWN.  NOTE THAT PARITY SWEEPS
	SETOM NO.ITS		; THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS
	MOV #15.*60.,DLXUP	;DON'T LET COUNTER OVERFLOW
	BR 12$			;BUT CHECK FOR COMMANDS ANYWAY (SALVAGER DISK)

11$:	CLR NO.ITS		;-10 HAS SETOMED COUNTER, IT'S UP
12$:	;FALL INTO CHKOST

; CHECK FOR OUTPUT-START FROM -10

CHKOST:	MOV TTYST,A		;LINE# TO START OUTPUT
	BEQ CHKOUT		;NONE.
	CLR TTYST		;TELL -10 IT'S BEEN PICKED UP
	MOV #TYORNG,B	
	MASK 5			;DON'T INTERFERE WITH P.I. LEVEL
	CALL PUT		;PUT IN RING, LATER WILL SEND IT BACK TO 10
	UNMASK

; CHECK FOR TTY OUTPUT SENT BY -10

CHKOUT:	MOV TYOLIN,I		;OUTPUT TO BE DONE?
	BEQ CHKIN		;NO.
	MOV TYOCNT,C		;YES, GET NUMBER OF CHARS
	CALL TYOSER		;CALL OUTPUT HANDLER
	CLR TYOLIN		;TELL 10 WE'VE GOBBLED THE OUTPUT
	BIS #DLX10I,DLXCSR	;GIVE TRANSFER-COMPLETE INTERRUPT

; CHECK FOR TTY INPUT TO BE SENT TO -10

CHKIN:	TST TYIRNG+RINGCT
	BEQ CHKDON		;NO STATUS TO BE STORED
	TST TYILIN
	BNE CHKDON		;PREVIOUS STATUS NOT PICKED UP
	MOV #TYIRNG,B
	CALL GET
	MOV A,TYICHR		;GIVE INPUT CHARACTER TO 10
	CALL GET
	MOV A,TYILIN		;GIVE LINE NUMBER TO 10
	BIS #DLX10I,DLXCSR	;SEND INTERRUPT TO 10

; CHECK FOR OUTPUT-DONE TO BE SENT TO -10

CHKDON:	TST TYORNG+RINGCT
	BEQ CHKHNG		;NO STATUS TO BE STORED
	TST TYOSTS
	BNE CHKHNG		;PREVIOUS STATUS NOT PICKED UP
	MOV #TYORNG,B
	CALL GET
	MOV A,I
	ASL I
	MOV BUFSIZ(I),TYOBSZ	;TELL -10 HOW MANY CHARS TO GIVE
	MOV A,TYOSTS		;GIVE OUTPUT DONE TO 10
	BIS #DLX10I,DLXCSR	;WITH INTERRUPT

; CHECK FOR HANGUPS TO BE SENT TO -10

CHKHNG:	TST HNGSIG		;ANY HANGUPS TO BE REPORTED?
	BEQ CHKLPR		;NO
	TST HNGLIN
	BNE CHKLPR		;PREVIOUS STATUS NOT PICKED UP
	MOV #LASTTY,I		;SCAN OVER ALL LINES
1$:	MASK 5
	MOV TTYHNG(I),A		;GET HANG-UP STATUS
	BNE 2$			;BRANCH IF FOUND SOMETHING TO REPORT
	UNMASK
	TST -(I)
	CMP I,#NFTTY
	BHIS 1$
	BPT			;HNGSIG OUT OF PHASE WITH TTYHNG

2$:	CLR TTYHNG(I)		;GOT STATUS, CLEAR IT
	DEC HNGSIG		;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED
	UNMASK			;NOW IT'S OK TO INTERRUPT AND SET TTYHNG
	MOV A,HNGLIN		;GIVE LINE NUMBER AND OTHER DATA TO 10
	BIS #DLX10I,DLXCSR	;WITH INTERRUPT

; CHECK FOR REQUEST FROM -10 TO SET LINE PARAMETERS

CHKLPR:	MOV LPRLIN,I		;LINE PARAMETERS TO BE SET?
	BEQ CHKCHS		;NO.
	ASL I			;YES, GET LINE INDEX
	MOV LPRLPR,A		;AND DH11 PARAMETER REGISTER VALUE
	MOV LPRBSZ,B		;AND BUFFER SIZE
	CALL SPARAM		;CALL PARAMETER SETTER
	CLR LPRLIN		;TELL 10 IT IS DONE

; CHECK FOR CHAOS NET ACTIVITY

CHKCHS:
.IFNZ CHAOSP
	CALL DLCWAK		;WAKEUP DL10-CHAOSNET STUFF
.ENDC ;CHAOSP
.IFNZ T300P
	CALL DSKSTR		;CHECK FOR DISK REQUEST
.ENDC ;T300P

; CHECK FOR EXAMINE/DEPOSIT REQUEST FROM -10

CHKEXD:	TST EXDSTS		;EXAMINE/DEPOSIT?
	BEQ CHKGLD		;NO.
	MOV EXDADR,A		;GET ADDRESS
	CMP EXDSTS,#2
	BNE 21$
	MOV EXDDAT,(A)		;DEPOSIT
21$:	MOV (A),EXDDAT		;EXAMINE
	CLR EXDSTS		;IT IS DONE

;CHECK FOR GOULD LPT OUTPUT

CHKGLD:
.IF EQ GOULDP
;	CLR GLPCTR		;IF NO GOULD, FLUSH OUTPUT FOR IT
;	SETOM GLPTER		;AND SAY "NOT READY"
	TST 10RQ
	BEQ 20$
	;10 WANTED US TO DO SOMETHING, PLAY WITH THE LIGHTS
	MOV LITHSE,A
	ROL A
	ROL LITHSE
20$:	MOV LITHSE,GLPTER
.IFF
	TST GLPCTR		;ANY BYTES IN BUFFER?
	BEQ 1$
	CALL GLPTYO		;YES, OUTPUT THEM
1$:	MOV GLPERR,GLPTER	;COPY ERROR STATUS FROM P.I. LEVEL TO -10
.ENDC				;DONE HERE SO NO USE OF DL10 AT P.I. LEVEL
;	BR MAINX

MAINX:	JMP MAIN		;THAT'S IT
MAINE::
.ENDC ;DL10P
.IFNZ DTE20P
	.SBTTL MAIN LOOP FOR DTE20

MAIN:	BIT #%D1RUN,DIAG1	;IS KL10 RUNNING?
	BEQ TENDED		;NO, LOSE!
	BIT #%D1ERR+%D1HLT,DIAG1	;HAS KL10 CLOCK STOPPED FOR HARDWARE ERROR? OR JRST 4
	BNE TENDED		;YES, LOSE!
	TST KLDCPF		;MAYBE USER WANTS TO GIVE A KLDCP COMMAND?
	BNE KLDCPR		;YES, RETURN TO KLDCP
	TSTB @DLKS+NFDLHX	;CTY INPUT?
	BPL 10$			;TEST KBD BEFORE CLK SINCE MIGHT BE MORE THAN
				; 1/60'TH SECOND PER TRIP AROUND THE LOOP.
	MASK 5			;YES, SIMULATE INTERRUPT
	CALL DL1IBK		;CAN'T USE REAL INTS BECAUSE WOULD INTERFERE WITH KLDCP
10$:	TSTB LKS		;60 CYCLE CLOCK TICK?
	BMI CLKSER		;YES
	BIT #%STINV,STATUS	;REQUEST FROM 10?
	BNE TENSER		;YES, SERVICE IT.
	BIT #%STDNI,STATUS	;TO10 XFER COMPLETE?
	BNE INPDON		;YES, SERVICE IT.
	BIT #%STDNO,STATUS	;TO11 XFER COMPLETE?
	BNE OUTDON		;YES, SERVICE IT.
	BIT #%STERI+%STERO,STATUS
	BNE LOSSAG		;BYTE TRANSFER LOST
	BR MAIN			;CLOSE LOOP

;60-CYCLE CLOCK SERVICE

CLKSER:	CLR LKS			;CLEAR CLOCK FLAG
	TST CLKENB		;DOES 10 WANT CLOCK INTERRUPTS?
	BEQ 1$
	D10MON			;YES, GIVE ONE
	    DTECLK		;SET CLOCK FLAG IN LOW CORE
	 BCS UHUNG
	MOV #%STINX,STATUS	;AND SEND INTERRUPT
1$:	CMP SWR,CURSWR		;MAYBE NEED TO UPDATE 10'S SWITCHES
	BEQ 2$
	MOV SWR,CURSWR
	TENSW			;LET KLDCP DO IT
	 BCS UHUNG
2$:	JSR B,HWEXAM		;INCREMENT COUNTER -10 IS SUPPOSED
	    DTECHK		; TO SETOM EVERY HALF-SECOND
	CLR LH
	CLR SNB
	INC RH
	BEQ 3$
	CMP RH,#15.*60.		;IF IT DOESN'T SETOM IT FOR 15 SECONDS
	BLE 4$			;THEN IT IS DOWN.  NOTE THAT PARITY SWEEPS
	SETOM NO.ITS		;THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS.
	MOV #15.*60.,RH		;DON'T LET COUNTER OVERFLOW
	BR 4$

3$:	CLR NO.ITS		;IT SETOMED COUNTER, IT'S UP.
4$:	JSR B,HWDEP		;PUT COUNTER BACK
	    DTECHK
	MASK 6			;NOW SIMULATE BR6 CLOCK INTERRUPT
	CALL CLKBRK
	BR TENSER		;AND GO SERVICE 10 (IN CASE LOST INTERRUPT)

; HERE IF KL10 HALTS

TENDED:	SETOM NO.ITS
	CLC
	RET			;LET KLDCP PRINT THE MESSAGE

; BYTE TRANSFER ENCOUNTERED HARDWARE LOSSAGE

LOSSAG:	BPT
	BR LOSSAG

; USER WANTS TO GIVE A KLDCP COMMAND

KLDCPR:	CLR KLDCPF
	SEC
	RET

TENSER:	JMP TENSR0

; HERE WHEN TO10 BYTE TRANSFER COMPLETE

INPDON:	MOV #%STCLI,STATUS	;CLEAR FLAGS IN DTE20
	MOV INPCMD,A		;GET COMMAND FOR XFER THAT JUST FINISHED
	BNE 1$
	 BPT			;WOOPS, NO XFER IN PROGRESS
1$:	CLR INPCMD		;NO XFER IN PROGRESS NOW
	MOV INPSVI,I
	MOV INPSVC,C
	CALL @FINAL-2(A)	;CALL APPROPRIATE FINISHER ROUTINE
	BR MAIN

; HERE WHEN TO11 BYTE TRANSFER COMPLETE

OUTDON:	MOV #%STCLO,STATUS	;CLEAR FLAG
	MOV OUTCMD,A		;GET COMMAND FOR XFER THAT JUST FINISHED
	BNE 1$
	 BPT			;WHOOPS, NO XFER IN PROGRESS
1$:	CLR OUTCMD		;NO XFER IN PROGRESS NOW
	MOV OUTSVI,I
	MOV OUTSVC,C
	CALL @FINAL-2(A)	;CALL APPROPRIATE FINISHER ROUTINE
	BR MAINJ

; HERE TO START TO10 BYTE TRANSFER.  HWEXAM OF DTEINP HAS BEEN DONE.

INPSER:	D10MON			;VALUE HAS BEEN PICKED UP, SETOM IT
	    DTEINP
	BIT #1000,LH		;RIGHT GENDER OF COMMAND?
	BEQ OUTSR1		;YES
	BR MAINJ		;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED

; HERE TO START TO11 BYTE TRANSFER.  HWEXAM OF DTEOUT HAS BEEN DONE.

OUTSER:	D10MON			;VALUE HAS BEEN PICKED UP, SETOM IT
	    DTEOUT
	BIT #1000,LH		;RIGHT GENDER OF COMMAND?
	BNE OUTSR1		;YES
	BR MAINJ		;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED

OUTSR1:	MOV RH,C		;GET BYTE COUNT
	MOVB LH,I		;GET LINE#
	MOVB LH+1,A		;GET COMMAND TIMES 2
	BEQ MAINJ		;CLEARING CORE?  IGNORE ZERO COMMAND
	BLE OUTSR2
	CMP A,#LBEGIN
	BGT OUTSR2
	CALL @BEGIN-2(A)	;CALL APPROPRIATE BEGIN-XFER ROUTINE
	BIT #2,A
	BNE 1$
	MOV A,INPCMD		;REMEMBER CRUFT FOR XFER IN PROGRESS
	MOV I,INPSVI
	MOV C,INPSVC
	BR MAINJ

1$:	MOV A,OUTCMD		;REMEMBER CRUFT FOR XFER IN PROGRESS
	MOV I,OUTSVI
	MOV C,OUTSVC
MAINJ:	JMP MAIN

OUTSR2:	BR MAINJ		;BAD COMMAND FROM 10 (USED TO BE BPT) JUST IGNORE IT

;TABLE OF ROUTINES TO PROCESS DATA TRANSFER COMMANDS FROM -10

BEGIN:	TYOSER			;%DTTYO
	;ETHISR			;%DTETI
	;ETHOSR			;%DTETO
LBEGIN==.-BEGIN

;TABLE OF ROUTINES TO FINISH UP DATA TRANSFERS

FINAL:	TYOFIN			;%DTTYO
	;ETHIFN			;%DTETI
	;ETHOFN			;%DTETO

;CHECK FOR COMMANDS FROM 10, STORE STATUS IN ANY STATUS WORDS
;THAT 10 HAS SET BACK TO -1

TENSR0:	MOV #%STUNV,STATUS	;CLEAR 10 INTERRUPTING 11 FLAG
	JSR B,HWEXAM		;CHECK FOR A NON-TIMESHARING COMMAND
	    DTECMD
	MOV RH,A		;IS THERE ONE?
	BEQ TENSR1		;NO, GO CHECK FOR TIMESHARING STUFF
	CLR LH
	CLR SNB
	CMP A,#377
	BHI 2$
1$:	TSTB TPS		;CHAR TO BE TYPED, WAIT FOR READY
	BPL 1$
	MOVB A,TPB		;TYPE IT OUT
9$:	CLR RH			;CLEAR OUT THE COMMAND
	JSR B,HWDEP
	    DTECMD
	D10MON			;TELL 10 IT'S DONE
	    DTEFLG
	JMP MAIN

2$:	CMP A,#%DTTYI
	BNE 5$
	CLR RH			;SNB,LH,RH NOW HAS ZERO
	SETOM DDTMOD		;KEYBOARD INPUT WANTED
	TST DDTCHR		;TEST IF READY
	BMI 3$			;IF NO INPUT, GIVE ZERO
	MASK 5
	MOV DDTCHR,RH		;GIVE THE CHAR
	COM DDTCHR		;MAKE NEGATIVE
	UNMASK
3$:	JSR B,HWDEP
	    DTEF11
	BR 9$

5$:	CMP A,#%DTCLN
	BNE 6$
	SETOM CLKENB
	BR 9$

6$:	CMP A,#%DTCLF
	BNE 7$
	CLR CLKENB
	BR 9$

7$:	BPT			;SOME COMMAND WE DON'T IMPLEMENT
	BR 9$			;IF CONTINUED, IGNORE IT

;CHECK FOR ITS UP/DOWN

TENSR1:	TST NO.ITS		;IF SYSTEM ISN'T UP,
	BNE MAINJ		;DON'T TRY TO HACK TS STUFF
	INC DLXOFF		;OTHERWISE, FIRST TIME THROUGH HERE
	BNE CHKOST		;WE CHECK THE VERSION
	JSR B,HWEXAM
	    DTEVER
	TST RH			;STORED?
	BNE 1$
	DEC DLXOFF		;NO, DON'T LOOK AT IT
	BR MAINJ		;PROBABLY CORE BEING CLEARED

1$:	CMP RH,VERSN
	BEQ CHKOST
	 BPT			;-10 AND -11 PROGRAMS NOT SAME VERSION

CHKOST:	JSR B,HWEXAM		;CHECK FOR 10 WANTING OUTPUT START
	    DTEOST
	BNE CHKTRN		;BRANCH IF LOCATION DTEOST IS -1
	D10MON			;HAVING PICKED IT UP, SET BACK TO -1
	    DTEOST
	MOV RH,A
	MOV #TYORNG,B
	MASK 5			;DON'T INTERFERE WITH P.I. LEVEL
	CALL PUT
	UNMASK
	CLR DDTMOD		;SYSTEM UP, TURN OFF DDT MODE
	MOV #-1,DDTCHR		;..

CHKTRN:	TST INPCMD
	BNE 1$			;INPUT IN PROGRESS, DON'T START AGAIN
	JSR B,HWEXAM		;CHECK FOR DATA TRANSFER COMMAND
	    DTEINP
	BNE 1$			;DTEINP -1, NO REQUEST
	JMP INPSER

1$:	TST OUTCMD
	BNE CHKLSP		;OUTPUT IN PROGRESS, DON'T START AGAIN
	JSR B,HWEXAM		;CHECK FOR DATA TRANSFER COMMAND
	    DTEOUT
	BNE CHKLSP		;DTEOUT -1, NO REQUEST
	JMP OUTSER

CHKLSP:	JSR B,HWEXAM		;CHECK FOR SET LINE SPEED COMMAND
	    DTELSP
	BNE CHKTYI
	MOV RH,I		;GET LINE#
	ASL I
	CMP I,#NFTTY		;VALIDATE IT
	BLO 1$			;IGNORE IF BAD
	CMP I,#LASTTY
	BHI 1$
	JSR B,HWEXAM		;GET LPR,,BUFFERSIZE
	    DTELPR
	MOV LH,A
	MOV RH,B
	CALL SPARAM		;DO IT
1$:	D10MON			;DONE, SETOM
	    DTELSP

CHKTYI:	TST TYIRNG+RINGCT
	BEQ CHKODN		;NO TTY INPUT WAITING
	JSR B,HWEXAM
	    DTETYI
	BEQ CHKODN		;PREVIOUS CHAR NOT PICKED UP
	MOV #TYIRNG,B
	CALL GET
	MOV A,RH		;CHAR
	CALL GET
	MOV A,LH		;LINE#
	CLR SNB
	JSR B,HWDEP		;GIVE 10 LINE#,,CHAR
	    DTETYI
	MOV #%STINX,STATUS	;INTERRUPT THE 10

CHKODN:	TST TYORNG+RINGCT
	BEQ CHKHNG		;NO OUTPUT DONES WAITING
	JSR B,HWEXAM
	    DTEODN
	BEQ CHKHNG		;PREVIOUS STATUS NOT PICKED UP
	MOV #TYORNG,B
	CALL GET		;GET LINE# WITH OUTPUT DONE
	MOV A,LH
	ASL A
	MOV BUFSIZ(A),RH
	CLR SNB
	JSR B,HWDEP		;GIVE 10 LINE#,,BUFFERSIZE
	    DTEODN
	MOV #%STINX,STATUS	;INTERRUPT THE 10

CHKHNG:	TST HNGSIG
	BEQ MAINX		;NO HANGUPS/DIALINS WAITING
	JSR B,HWEXAM
	    DTEHNG
	BEQ MAINX		;PREVIOUS STATUS NOT PICKED UP
	MOV #LASTTY,I		;SCAN OVER ALL LINES
1$:	MASK 5
	MOV TTYHNG(I),A		;GET HANG-UP STATUS
	BNE 2$			;BRANCH IF FOUND SOMETHING TO REPORT
	UNMASK
	TST -(I)
	CMP I,#NFTTY
	BHIS 1$
	BPT			;HNGSIG OUT OF PHASE WITH TTYHNG

2$:	CLR TTYHNG(I)		;GOT STATUS, CLEAR IT
	DEC HNGSIG		;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED
	UNMASK			;NOW IT'S OK TO INTERRUPT AND SET TTYHNG
	MOV A,RH		;GIVE LINE NUMBER AND OTHER DATA TO 10
	CLR LH
	CLR SNB
	JSR B,HWDEP
	    DTEHNG
	MOV #%STINX,STATUS	;INTERRUPT THE 10

MAINX:	JMP MAIN
.ENDC ;DTE20P

.IFZ DL10P+DTE20P
	.SBTTL MAIN LOOP FOR AI

MAIN:
.IIF NZ TEN11P, CALL T11WAK	;CHECK UP ON TEN-11 INTERFACE
.IIF Z TEN11P, CALL CHSRUN	;DAMNED THING GETS WEDGED
.IFNZ ETHERP
	TST CHXRTF+CHXETH	;NEED TO BROADCAST ROUTING INFO TO ETHERNET?
	BEQ 666$
	CALL ETHRUT
666$:
.ENDC ;ETHERP
	TST WAKE		;CLOCK TICK?
	BEQ MAIN		;NO, JUST WAIT
	CLR WAKE		;CLOCK HAS TICKED, CLEAR FLAG
	BR MAIN			;NOT MUCH TO DO, NO TTYS
.ENDC ;DL10P+DTE20P

	.SBTTL OUTPUT HANDLERS

TYOSER:	ASL I				;CONVERT -10 LINE# TO -11 TTY INDEX
	CMP I,#NFTTY
	BLO 11$
	CMP I,#LASTTY
	BLOS 12$
11$:	BPT				;10 GAVE BAD LINE#
12$:	MOV HDWR(I),H			;GET HARDWARE INDEX
	MOV BUFPNT(I),D			;AND ADDRESS OF TYPEOUT BUFFER
	CMP BUFSIZ(I),C			;MAKE SURE THERE IS ROOM IN BUFFER
	BHIS 2$
	 BPT				;THERE ISN'T
2$:	MOV C,B				;MUSTN'T CLOBBER BYTE COUNT IN C
.IFNZ DL10P
	MOV #TYOPNT,A			;GET CRUFT FROM DL10
3$:	MOVB @A,(D)+			;COPY BUFFER
	SOB B,3$
.ENDC ;DL10P
.IFNZ DTE20P
	MOV D,TO11AD			;SET UP BYTE TRANSFER
	NEG B
	BIC #050000,B			;SET LAST, BYTE; CLEAR ASCIZ, 2.4
	MOV B,TO11BC			;START XFER
	RET

TYOFIN:	MOV HDWR(I),H			;COMES BACK WHEN XFER COMPLETE
.ENDC ;DTE20P

;BUFFER HAS BEEN LOADED, START DEVICE

	MASK 5				;DON'T LET DEVICE INTERRUPT
	MOV BUFPNT(I),D
	CALL @STROUT(H)			;CALL DEVICE-DEPENDENT ROUTINE
	MOV #40000,TYPING(I)		;TELL 10 WHEN OUTPUT FINISHES (LARGE POSITIVE NUMBER)
	UNMASK
	RET

;GIVE MESSAGE.  A -> .WORD LENGTH,MSG.  I HAS LINE NUMBER.

GIVMSG:	PUSH <C,D>
	MOV (A)+,C		;C HAS BYTE COUNT, A HAS ADDRESS
	MOV A,D			;PUT ADDRESS IN D
	MOV HDWR(I),H
	MASK 5
	CALL @STROUT(H)		;START OUTPUT TO LINE
	UNMASK
	POP <D,C>
	RET

ASPACK:	MNAME ^%
	MSG ^\
�Connected to MCHN'.\%
DWNMSG:	MSG ^\
�ITS is down.\
IBOMSG:	MSG ^\IBO\

;DEVICE-DEPENDENT OUTPUT START ROUTINES  (CALL AT PI LEVEL 5)
;H HDWR IDX, I TTY IDX, D BUFFER POINTER, C NUMBER OF BYTES

STRDH:	BIC DHLBIT(I),@DHBAR(H)		;IF LINE ALREADY TRANSMITTING, STOP IT
					;IT SHOULDN'T OUGHT TO BE...
	MOV DHLSEL(I),@DHSCR(H)		;HARDWARILY SELECT THIS LINE
	MOV D,@DHCA(H)			;SET XMT ADDRESS
	NEG C				;HARDWARE LIKES NEGATIVE BYTE COUNTS
	MOV C,@DHBC(H)			;SET XMT COUNT
	BIS DHLBIT(I),@DHBAR(H)		;START TRANSMISSION HARDWARILY
	BIS DHLBIT(I),DHOAC(H)		;SOFTWARILY ALSO
	RET

STRDL:	MOV D,DLCA(H)
	MOV C,DLBC(H)
	CLR @DLPS(H)
	MOV #300,@DLPS(H)		;CAUSE INTERRUPT
	SETOM DLOAC(H)
CPOPJ:	RET

.IFNZ NMPTYS
STRMPK:	TST MPXENB
	BEQ CPOPJ
	MOV D,MPXPNT-NFMPTY(I)		;QUEUE OUTPUT
	MOV C,MPXNBT-NFMPTY(I)
STRMPX:	PUSH I
	TST MPXOAC			;START THE MPXR
	BNE 10$				;ALREADY BUSY
	CLR I
	MOV #NMPTYS,D
2$:	MOV MPXNBT(I),C			;FIND MPX KLUDGE LINE WANTS TO OUTPUT
	BNE 15$
	TST (I)+
	SOB D,2$
10$:	POP I
	RET

15$:	MOV I,MPXOLN			;SAVE LINE# OUTPUT ON
	ASR I				;SET UP HEADER
	ADD #200,I
	MOVB I,MPXHED
	MOVB C,MPXHED+1
	MOV #-1,MPXOAC			;SEND HEADER
	MOV #MPXIDX,I
	MOV HDWR(I),H
	MOV #MPXHED,D
	MOV #2,C
	CALL @STROUT(H)
	BR 10$
.ENDC ;NMPTYS

.IFNZ GOULDP
.SBTTL GOULD LPT OUTPUT (M.P. LEVEL)
.IIF Z DL10P, .ERROR GOULD LPT ONLY CODED FOR DL10
.ERR BY THE WAY, THESE ROUTINES DON'T WORK WORTH GUBBISH

GLPTYO:	MOV GLPOIP,H		;GET NEXT BUFFER
	CMP GB.STA(H),#%GBMP
	BEQ 2$			;BRANCH IF M.P. ACTIVE
	BLT 1$			;BRANCH IF IDLE BUFFER AVAIL
	RET			;NO FREE BUFFERS

1$:	CALL GLPBGB		;GOBBLE A BUFFER
2$:	MOV GB.PNT(H),D
	MOV GLPCTR,C		;SET UP BYTE COUNTER
	MOV GLPGRF,GLPGF1	;COPY ARG FROM 0 FOR SPEED
	TST GLIMBF		;CHAR SAVED FROM LAST TIME?
	BEQ GLPNCL
	CLR GLIMBF		;YES, PRINT IT
	MOVB GLIMBO,A
	CALL GLPPUT
	MOVB GLIMBO+1,A		;SECOND CHAR?
	BEQ GLPNCL
	CLR GLIMBO
	CALL GLPPUT

;CHARACTER PROCESSING LOOP
;C HAS # CHARS YET TO GO, D HAS WHERE TO PUT THEM, H -> BUFFER
;A WILL HAVE CHAR

GLPNCL:	MOV GLPPTR,A		;GET NEXT CHAR
	TST GLPGF1
	BNE GLPNRM		;GRAPHIC MODE, NO CHARACTER PROCESSING
	CMP A,#177		;ESCAPE?
	BEQ GLPESC
	CMP A,#40		;CONTROL?
	BGE GLPNRM		;NO, NORMAL PRINTING
	CMP A,#14		;CHECK FOR SPECIAL CONTROLS
	BNE 10$
8$:	CLR GLPROW		;START NEW PAGE
	TST GLPCOL		;IN MIDDLE OF LINE?
	BEQ 9$			;NO, OK
	CALL GLPBWW		;OTHERWISE, HAIR
	CLR GLPFIL		;HACK HACK MAKE FF NEXT LINE
	BR GLPNB1

9$:	SETOM GB.FF(H)
	BR GLPNXC

10$:	CMP A,#12
	BNE 12$
	INC GLPROW
	CMP GLPROW,#GLPRMX
	BHIS 8$			;SKIP OVER PERFORATION
	TST GLPCOL
	BNE GLPNBF		;IF NOT A BLANK LINE, FINISH BUFFER
	INC GB.NL(H)
	BR GLPNXC

12$:	CMP A,#11
	BNE 15$
13$:	MOV #40,A		;TAB - SPACE OVER
	CALL GLPPUT
	BIT #7,GLPCOL
	BNE 13$
	BR GLPNXC

15$:	CMP A,#15
	BEQ GLPNXC		;IGNORE CR
	CMP A,#33
	BNE 16$
	MOV #'$,A		;PRINT ALTMODE AS DOLLAR
	BR GLPNRM

16$:	BIS #100,A		;RANDOM CONTROL AS UPARROW, LETTER
	MOVB A,GLIMBO+1
	MOV #'^,A
	CALL GLPPUT
	MOVB GLIMBO+1,A
	CLR GLIMBO	
GLPNRM:	CALL GLPPUT		;HERE FOR NORMAL CHARACTER
GLPNXC:	DEC C			;HERE TO GOBBLE CHARACTER
	BGT GLPNCL		;BRANCH IF MORE CHARS TO GO
	BR GLPEND		;BUFFER EMPTIED

GLPNBF:	CALL GLPBWW		;HERE TO ADVANCE TO NEXT BUFFER
GLPNB1:	CMP GB.STA(H),#%GBIDL	;NEXT BUFFER AVAIL?
	BNE GLPEN1		;NO, STOP
	CALL GLPBGB		;YES, GOBBLE IT
	BR GLPNXC

GLPESC:	DEC C			;HERE FOR TWO CHAR ESC SEQ
	BEQ GLPEND		;-10 FORGOT 2ND CHAR, FLUSH
	MOV GLPPTR,A		;GET & DECODE 2ND CHAR
	CMP A,#105		;EOF
	BEQ GLPEOF
	BR GLPNXC		;OTHER CHARS ARE IGNORED

GLPEOF:	CLR GLPFIL
	CLR GLPROW
	CALL GLPBWW		;EOF, WRITE LAST BUFFER
GLPEN1:	DEC C			;GOBBLE A CHARACTER
GLPEND:	MOV C,GLPCTR		;HERE WHEN DONE, RELEASE 10'S BUFFER
	CMP GB.STA(H),#%GBMP	;BUFFER ACTIVE AT M.P. LEVEL?
	BNE 1$			;IF NOT, DON'T CLOBBER GB.PNT
	MOV D,GB.PNT(H)		;IF SO, REMEMBER AMT OF STUFF IN CURRENT BUFFER
1$:	RET			;RETURN TO MAIN LOOP

;OUTPUT PRINTING CHAR IN A

GLPPUT:	CMP D,GLPLIM		;LINE OVERFLOW?
	BLO 5$			;NO
	CALL GLPBWW		;YES, DONE WITH THIS BUFFER
	INC GLPROW		;OUGHT TO CHECK FOR PERFORATION, BUT...
	CMP GB.STA(H),#%GBIDL	;MORE BUFFERS?
	BNE 6$			;NO
	CALL GLPBGB
5$:	MOVB A,(D)+		;DROP CHAR IN BUFFER
	INC GLPCOL		;AND ADVANCE COLUMN
	RET

6$:	MOVB A,GLIMBO		;NO BUFFERS, SAVE CHAR BEING PRINTED
	SETOM GLIMBF		;SET FLAG SO WILL BE PRINTED NEXT TIME
	TST (SP)+		;STOP THE WORLD
	BR GLPEN1

;GOBBLE IDLE BUFFER H -> FOR M.P.  RETURNS GB.PNT(H) IN D.

GLPBGB:	MOV #%GBMP,GB.STA(H)	;ACTIVATE AT M.P. LEVEL
	CLR GB.FF(H)		;INIT THE BUFFER
	CLR GB.NL(H)
	CLR GLPCOL		;START LINE IN COLUMN 0
	MOV H,D			;INIT INSERT POINTER
	ADD #GB.DAT,D
	MOV D,GB.PNT(H)
	MOV H,GLPLIM		;SET UP MAX. VALUE OF GB.PNT
	ADD #GB.LEN,GLPLIM
	RET

;GIVE BUFFER H -> TO P.I. LEVEL

GLPBWW:	BIT #1,D		;MUST BE EVEN NUMBER OF BYTES
	BEQ 1$
	CLRB (D)+

1$:	PUSH A			;INTERFACE GETS BYTES IN WRONG ORDER
	MOV P,A			;COMPUTE NUMBER OF WORDS IN LINE
	SUB H,A
	SUB #GB.DAT,A
	ASR A
	BNE 4$
	CLR (D)+		;CAN'T HAVE ZERO-LENGTH LINE
	INC A
4$:	MOV A,GB.PNT(H)		;SAVE WORD COUNT FOR P.I. LEVEL
2$:	SWAB -(D)
	SOB A,2$
	POP A
	TST GLPFIL		;IF STARTING NEW FILE,
	BNE 5$
	SETOM GLPFIL
	SETOM GB.FF(H)		; BE SURE TO GET NEW PAGE
5$:	MOV #%GBWRT,GB.STA(H)	;QUEUE TO P.I. LEVEL
	MOV GB.NXT(H),H		;ADVANCE TO NEXT BUFFER
	MOV H,GLPOIP
	MASK 6			;STOP P.I. LEVEL (HAVE TO LOCK OUT GLPBRK & CLKBRK)
	TST GLPOAC		;PRINTER ON?
	BNE 3$			;YUP
	MOV #%GCOFF,@#GLPCSR	;NO, CLEAR OLD STUFF IN INTERFACE
	TST GLPGF1		;AND PUT IN LOW-SPEED GRAPHIC MODE IF NECC	
	BEQ 6$
	MOV #%GCGRF,@#GLPCSR
	MOV #%GCLSL,@#GLPCSR	;LOW SPEED (COME ON, THIS IS ONLY A KL10!)
6$:	MOV #%GCON,@#GLPCSR	;TURN IT ON
	MOV #%GCION,@#GLPCSR	;TURN ON INTERRUPTS
	SETOM GLPOAC
;	PUSH @#PS		;FAKE AN INTERRUPT
;	CALL GLPBRK		;IS THIS NECESSARY?
3$:	UNMASK
	RET

;GOULD LPT VARIABLES

GLPCOL:	0		;CURRENT COLUMN NUMBER
GLPROW:	0		;CURRENT ROW NUMBER
 GLPRMX==67.		;NUMBER OF LINES PER PAGE
GLPLIM:	0		;ADDRESS OF END OF CURRENT BUFFER
GLPOAC:	0		;NON-ZERO => GOULD LPT P.I. ACTIVE
GLPGF1:	0		;NON-ZERO => GOULD LPT IN GRAPHIC MODE
GLIMBO:	0		;SAVE CHAR HERE WHEN RUN OUT OF BUFFERS
GLIMBF:	0		;NON-ZERO => CHAR IN GLIMBO
GLPFIL:	0		;NON-ZERO => IN MIDDLE OF A FILE
GLPTIM:	10.		;COUNT DOWN WHEN LOSING
GLPERR:	0		;NON-ZERO => ERROR STATUS FROM P.I.
.ENDC	;GOULDP

	.SBTTL T-300 DISK

.IFNZ T300P

;DISK UNIBUS REGISTERS

DSKCRA=176700			;COMPLETION REGISTER A
 %DAPON==100000			;SPONTANEOUS COMPLETION DUE TO POWER-ON.  DISK NUMBER
				; IN LOW BITS OF COMMAND-COMPLETION REGISTER B
 %DACQE==10000			;CONSISTENCY ERROR IN COMMAND QUEUE
 %DANXM==4000			;NXM ERROR IN COMMAND QUEUE
 %DAPAR==2000			;PARITY ERROR IN COMMAND QUEUE
				;LOW 2 BITS OF COMMAND COMPLETION REGISTER A AND
				;COMMAND COMPLETION REGISTER B CONTAIN THE ADDRESS
				;OF THE PARITY OR NXM ERROR
DSKCRB=176702			;COMPLETION REGISTER B
DSKCSR=176704			;COMMAND/STATUS REGISTER
 %DCCPL==100000			;COMMAND IS COMPLETE, RESET BY %DCACK.  READ-ONLY
 %DCDER==40000			;"DMA ERROR", RESET ONLY BY SYSTEM RESET.
				;1=NORMAL, 0=ERROR
				;BITS 30004 ALWAYS ON
 %DCMNT==4000			;HOST-ADAPTOR MAINTENANCE MODE
 %DCRST==2000			;RESET.  WRITE-ONLY.
 %DCACK==1000			;ACKNOWLEDGE COMMAND COMPLETION.  WRITE-ONLY
 %DCCMD==400			;TAKE COMMAND FROM CTRA/CTRB.  WRITE-ONLY
 %DCRDY==200			;READY TO TAKE A COMMAND.  READ-ONLY
 %DCTIE==100			;COMMAND TRANSMISSION (%DCRDY) INTERRUPT ENABLE
 %DCCIE==40			;COMMAND COMPLETION (%DCCPL) INTERRUPT ENABLE
 %DCPCY==20			;POWER JUST CYCLED ON OR OFF.  READ-ONLY
 %DCPON==10			;POWER ON.  READ-ONLY
 %DCDMA==2			;DMA IN PROGRESS.  READ-ONLY
 %DCBOT==1			;BOOT (READ DRIVE 0 SECTOR 0 INTO MEMORY 0).  WRITE-ONLY
DSKCTA=176706			;COMMAND TRANSMISSION A (ADDRESS OF RQB HIGH BITS)
DSKCTB=176710			;COMMAND TRANSMISSION B (ADDRESS OF RQB LOW BITS)
;176714 DUPLICATES DSKCSR FOR UNKNOWN REASONS

;DISK REQUEST BLOCK.  WE ONLY HAVE ONE SINCE NO SEEK OVERLAP.

RQBACT:	0		;NON-ZERO IF REQUEST ACTIVE AND EXPECTING COMPLETION

RQBID:	0		;RETURNED IN CCRB WHEN COMMAND COMPLETES
RQBSTS:	0		;STATUS STORED BY 2561, COPIED INTO DSCSTS
RQBFLT:	0		;FAULT CODE IN HIGH BYTE, BITS 1-0 HIGH BITS OF LINK ADDRESS
RQBLNK:	0		;LINK ADDRESS TO NEXT RQB (MUST BE ZERO)
RQBCMD:	0		;COMMAND CODE, COPIED FROM DSCCMD
RQBDRV:	0		;UNIT NUMBER, COPIED FROM DSCDRV
RQBCYL:	0		;CYLINDER NUMBER, COPIED FROM DSCCYL
RQBHED:	0		;HEAD NUMBER, COPIED FROM DSCHED
RQBSEC:	0		;SECTOR NUMBER, COPIED FROM DSCSEC
RQBWC:	0		;POSITIVE WORD COUNT (ALWAYS 12.*256.)
RQBMA:	0		;MEMORY ADDRESS (ALWAYS DSKBUF)
RQBMAH:	0		;MEMORY ADDRESS HIGH (ALWAYS 0)
			; BITS 1-0 BITS 17-16 OF ADDRESS.  BIT 6 MA INCR INH
RQBID1:	0		;RETURNS RECORD ID 1
RQBID2:	0		;RETURNS RECORD ID 2
RQBMNT:	.BLKW 27.	;DIAGNOSTIC DATA MAY BE RETURNED

;DISK BUFFER.  HOLDS ENOUGH 12-BIT BYTES IN 16-BIT WORDS TO MAKE 1024. 36-BIT WORDS
DSKBUF:	.BLKW 3.*1024.

;ROUTINE TO START DISK IF IT IS READY AND THERE IS A REQUEST.
DSKSTR:	TST DSCREQ		;ANY REQUEST FROM 10?
	BEQ 99$			;NO, EXIT
	CMP DSCCHK,#2561
	BNE 99$			;CHECK WORD WRONG, DON'T TOUCH DISK
	TST RQBACT		;PREVIOUS OPERATION FINISHED?
	BEQ 10$
	BPT			;NO, MUST BE BUG IN 10?
10$:	TSTB DSKCSR		;TEST IF READY FOR COMMAND TRANSMISSION
	BPL 99$			;NO, WAIT
	CLR DSCDON		;YES, CLEAR 10/11 COMMUNICATION FLAGS
	CLR DSCREQ
	CLR RQBLNK		;SET UP RQB FROM 10'S PARAMETERS
	MOV DSCCMD,RQBCMD
	MOV DSCDRV,RQBDRV
	MOV DSCCYL,RQBCYL
	MOV DSCHED,RQBHED
	MOV DSCSEC,RQBSEC
	MOV #12.*256.,RQBWC
	MOV #DSKBUF,RQBMA
	CLR RQBMAH
	CMP RQBCMD,#%DMWRT	;IF A WRITE COMMAND, MUST COPY DATA BUFFER
	BNE 30$
	MOV #DSKBUF,D
	.REPT 4			;TAKES 4 BYTE POINTERS TO DO IT
	MOV #DSCPNT+<2*.RPCNT>,H
	.REPT 3			;EACH BYTE POINTER HAS 768 12-BIT BYTES
	MOV #256.,C
	CALL MOVHD
	.ENDR	
	.ENDR
30$:	CLR DSKCTA		;GIVE ADDRESS OF RQB TO 2561
	MOV #RQBID,DSKCTB
	SETOM RQBACT		;TELL INTERRUPT LEVEL INTERRUPT EXPECTED
	MOV #%DCCMD+%DCCIE,DSKCSR	;GIVE COMMAND, ENABLE COMPLETION INTERRUPT
99$:	RET			;DONE

;CALL HERE WHEN DISK INTERRUPTS
DSKBRK:	PUSH <A,B,C,D,H,I>	;SAVE ALL REGISTERS
	MOV DSKCSR,A
	BIT #%DCPCY,A		;POWER CYCLED?
	BNE 5$			;YES, RESET CONTROLLER AND IGNORE INTERRUPT
	BIT #%DCMNT,A		;NO, MAINTAINENCE MODE
	BEQ 4$			;OK
	BPT			;BLEAH, MUST BE BROKEN
	BR 5$

4$:	BIT #%DCDER,A		;WHAT ABOUT UNIBUS ERROR
	BNE 10$
	BPT
5$:	MOV #%DCRST,DSKCSR	;RESET THE CONTROLLER AND TURN OFF INTERRUPTS
	TST RQBACT		;DID THIS LOSE IN THE MIDDLE OF A DISK OPERATION?
	BEQ 99$			;NO, DISMISS
	MOV #%DFRST,A		;YES, GIVE ERROR STATUS
	CLR B
	BR 20$

10$:	BIT #%DCCPL,A		;TEST FOR COMMAND COMPLETION
	BPL 99$			;NO, IGNORE INTERRUPT
	MOV DSKCRA,A		;GET COMPLETION STATUS
	MOV DSKCRB,B
	MOV #%DCACK+%DCCIE,DSKCSR	;ACKNOWLEDGE COMPLETION, ENABLE MORE INTERRUPTS
	TST RQBACT		;EXPECTED?
	BEQ 99$			;NO, IGNORE
	BIT #%DAPON,A		;POWER-UP INDICATION?
	BNE 99$			;FOR NOW, IGNORE IT
	BIT #%DACQE+%DANXM+%DAPAR,A
	BEQ 30$			;OK, NO COMMAND-QUEUE ERROR
	MOV #%DCRST,DSKCSR	;RESET CONTROLLER (I DON'T KNOW IF IT NEEDS IT)
20$:	MOV A,DSCFLT		;COMMAND-QUEUE ERROR, GIVE STATUS TO PDP10
	MOV B,DSCSTS
	BR 80$

30$:	CLR DSCFLT		;CLEAR HIGH BYTE
	MOVB RQBFLT+1,DSCFLT	;PICK UP FAULT CODE, PUT IN LOW BYTE
	BEQ 35$			;IF FAULT CODE IS NON-ZERO, THE THING MAY BE FROZEN,
	MOV #%DCRST,DSKCSR	;SO RESET IT.  OTHERWISE ERROR SEEMS TO HAPPEN OVER AND OVER
35$:	MOV RQBSTS,DSCSTS	;GIVE STATUS TO PDP10
	MOV RQBCYL,DSCCYL	;STORE BACK DISK ADDRESS, MAY BE USEFUL TO PDP10
	MOV RQBHED,DSCHED
	MOV RQBSEC,DSCSEC
	BIT #%DMRED,RQBCMD	;IF COMMAND WAS READ, COPY BUFFER BACK
	BEQ 80$
	MOV #DSKBUF,D
	.REPT 4			;TAKES 4 BYTE POINTERS TO DO IT
	MOV #DSCPNT+<2*.RPCNT>,H
	.REPT 3			;EACH BYTE POINTER HAS 768 12-BIT BYTES
	MOV #256.,C
	CALL MOVDH
	.ENDR
	.ENDR
80$:	SETOM DSCDON		;SIGNAL PDP10 OPERATION IS COMPLETE
	BIS #DLX10I,DLXCSR	;AND INTERRUPT THE PDP10
	CLR RQBACT		;NO LONGER EXPECTING COMPLETION ON THE RQB
99$:	POP <I,H,D,C,B,A>	;RESTORE REGISTERS AND EXIT INTERRUPT
	RTI
.ENDC ;T300P

	.SBTTL SET LINE PARAMETERS

;LINE INDEX IN I
;DH11 PARAM REG IN A
;BUFFER SIZE IN B

SPARAM:	CMP I,#NFTTY
	BGE 1$
	 BPT
1$:	CMP I,#LASTTY
	BLE 2$
	 BPT
2$:	CMP B,#1.		;MINIMUM BUFFER SIZE ONE CHARACTER
	BGE 3$
	 MOV #1.,B
3$:	CMP B,#MAXBSZ		;MAXIMUM BUFFER SIZE <MAXBSZ> CHARACTERS
	BLE 4$
	 MOV #MAXBSZ,B
4$:	MOV B,BUFSIZ(I)		;SET AMOUNT OF BUFFER TO BE USED FROM NOW ON
	MOV HDWR(I),H		;(BUT NO LONGER DO WE ATTEMPT DYNAMIC BUFFER ALLOCATION)
	CMP H,#NLDHHX
	BHI 5$
	MASK 5			;LINE IS A DH11, HAVE TO SET LINE PARAM REG
	MOV DHLSEL(I),@DHSCR(H)	;SELECT THE LINE
	MOV A,@DHLPR(H)		;GIVE LINE-PARAMETER REG TO DH11
	UNMASK
5$:	MOV A,LPRVAL(I)		;STORE LPR IN CASE SOMEONE IS CURIOUS
	RET

	.SBTTL DH11 INPUT INTERRUPT

.REPT NDHS
CONC DH,\.RPCNT+1,<IBK:	JSR H,DHIBK>
	  2*.RPCNT
.ENDR

DHIBK:	MOV (H),H			;PICK UP HARDWARE INDEX
	PUSH <A,B,I>
1$:	MOV @DHNRC(H),A			;RECIEVE A CHARACTER
	BPL DHIEX			;EXIT INTERRUPT IF NO MORE CHARS
	MOV A,I				;EXTRACT LINE NUMBER
	SWAB I
	BIC #177760,I
	ASL I
	ADD DHTYNO(H),I
.IFNZ NDHUN
	CMP I,#NLDHTY			;IGNORE NON-EXISTENT LINES
	BHI 1$
.ENDC
	CALL @TTYIPC(I)			;CALL LINE HACKER
	BR 1$				;AND CHECK FOR MORE

DHIEX:	POP <I,B,A,H>
	RTI

;NORMAL DH11 INPUT

DHNRMI:	BIT #%DXPAR,A
	BEQ 1$				;IGNORE IF PARITY ERROR
10$:	 RET
1$:	BIT #%DXBRK,A			;IF BREAK,
	BEQ RCV
	TST AUTOSP(I)			;AND LINE WANTS AUTOSPEED-ON-BREAK FEATURE
	BPL 10$
ASPMD:	MOV #DHASP,TTYIPC(I)		;PUT IT IN AUTOSPEED MODE
	MOV DHLSEL(I),@DHSCR(H)		;AND SET HARDWARE TO 1200 BAUD
	MOV #023103,@DHLPR(H)
	RET

;CHAR IN A RECEIVED FROM LINE IN I
RCV:	BIC #177400,A			;8-BIT CHAR RECEIVE
RCV.FW:	TST NO.ITS			;ENTER HERE FOR FULL WORD RECEIVE
	BEQ 10$
21$:	MOV #DWNMSG,A			;ITS DOWN, GIVE MESSAGE
12$:	CALL GIVMSG
	RET

10$:	MOV #TYIRNG,B
	CMP RINGCT(B),#TYIRSZ-2
	BGT 11$
	CALL PUT			;FIRST PUT THE CHARACTER
	MOV I,A
	ASR A
	CALL PUT			;THEN THE TENNISH LINE NUMBER
	RET

11$:	MOV #IBOMSG,A			;INPUT BUFFER OVERFLOW
	BR 12$

.IFNZ NMPTYS		;HANDLE INPUT FROM THE MULTIPLEXOR LINE
MPXINP:	TST MPXENB
	BEQ RCV
	MOV MPXSEL,I			;CURRENT INPUT LINE
	TSTB A				;SPECIAL CHAR?
	BMI 1$
	JMP @TTYIPC(I)			;NO, RECEIVE ON APPROP LINE

1$:	MOV A,I				;SPECIAL CHAR, EXTRACT LINE#
	BIC #177700,I
;FOLLOWING FEATURE COMMENTED OUT SINCE IT CAUSES 11 TO LOOP
; WHEN NEXT INPUT ARRIVES -- NOT OBVIOUS HOW TO FIX.
;	CMP I,#77			;SELECT NON-MULTIPLEX INPUT?
;	BEQ 3$				;YES, DO SO
	ASL I
	ADD #NFMPTY,I
	CMP I,#LASTTY
	BHI 2$				;OUT OF RANGE, IGNORE
	MOV I,MPXSEL			;INPUT SELECT, SAVE LINE#
2$:	RET

3$:	MOV #MPXIDX,MPXSEL		;SELECT PASS THROUGH
	RET
.ENDC ;NMPTYS

;AUTOSPEED MODE COMES HERE WHEN CHAR RECIEVED

DHASP:	BIC #177400,A			;CLEAR FRAMING ERR, ETC.
	BEQ ASP10			;11 0'S = 110 BAUD
	CMP A,#200			;7 0'S, 1 = 150 BAUD
	BEQ ASP15
	CMP A,#170			;3 0'S, 4 1'S, 0 = 300 BAUD
	BEQ ASP30
	CMP A,#370			;300/600 IS NOW RUBOUT, NOT I
	BEQ ASP36
	CMP A,#146			;1 0, 2 1'S, 2 0'S, ... = 600
	BEQ ASP60
	CMP A,#340			;5 0'S, 3 1'S ? MYSTERY TO ME
	BEQ ASP60
	CMP A,#015			;CR = 1200
	BEQ ASP120
	CMP A,#215			;CR WITH EITHER PARITY
	BEQ ASP120
	MOV A,#.			;SAVE GARBAGE FOR DEBUGGING
	RET				;SOMETHING ELSE, IGNORE

ASP10:	MOV #006307,A			;110 IN, 110 OUT, NO PARITY, 8 BITS, EXTRA STPBT
	MOV #5,B
	MOV #12200,-(SP)
	BR ASPX

ASP15:	MOV #012503,A			;150 IN, 150 OUT, NO PARITY, 8 BITS
	MOV #7,B
	MOV #13300,-(SP)
	BR ASPX

ASP30:	MOV #016703,A			;300 IN, 300 OUT, NO PARITY, 8 BITS
	MOV #15.,B
	MOV #14400,-(SP)
	BR ASPX

ASP36:	MOV #020703,A			;300 IN, 600 OUT, NO PARITY, 8 BITS
	MOV #30.,B
	MOV #14100,-(SP)
	BR ASPX

ASP60:	MOV #021003,A			;600 BAUD, NO PARITY, 8 BITS
	MOV #30.,B
	MOV #11100,-(SP)
	BR ASPX

ASP120:	MOV #023103,A			;1200 IN, 1200 OUT, NO PAR, 8 BITS
	MOV #60.,B
	MOV #15500,-(SP)
	BR ASPX

ASPX:	CALL SPARAM			;SET BUFFER SIZE AND HARDWARE SPEED
	MOV I,A				;SET UP SET-SPEED COMMAND TO -10
	ASR A
	BIS (SP)+,A
	TST TTYHNG(I)			;IF THIS IS NEW STATUS FOR 10,
	BNE 11$
	INC HNGSIG			;INDICATE STATUS WAITING
11$:	MOV A,TTYHNG(I)			;SAVE THIS LINE'S LATEST STATUS
	MOV #ASPACK,A			;ACKNOWLEDGE TO USER THAT HE WON
	CALL GIVMSG
	DEC TYPING(I)			;IF NO WAKEUP FOR 10, HIT CALL WHEN TYPING DONE
	MOV NRMIPC(I),TTYIPC(I)		;AND TAKE LINE OUT OF AUTOSPEED MODE
	RET

	.SBTTL DH11 OUTPUT INTERRUPTS

.REPT NDHS
CONC DH,\.RPCNT+1,<OBK:	JSR H,DHOBK>
	  2*.RPCNT
.ENDR

DHOBK:	MOV (H),H			;GET HARDWARE UNIT NUMBER
	BIT #DHSNXM,@DHSCR(H)		;IS THIS INTERRUPT DUE TO NXM?
	BEQ 1$
	 BPT				;YES
1$:	BIC #DHTDON,@DHSCR(H)		;HARDWARE KLUDGE TO MAKE INTERRUPTS WIN
	PUSH <A,B,C,I>
	MOV DHOAC(H),C			;SEE WHICH BAR BITS HAVE TURNED OFF
	BIC @DHBAR(H),C
	BIC C,DHOAC(H)
	MOV DHTYNO(H),I
	ADD #15.*2,I
2$:	BIT DHLBIT(I),C
	BEQ 4$
.IFNZ NMPTYS
	CMP I,#MPXIDX
	BNE 3$
	CALL MPXDON
.ENDC ;NMPTYS
3$:
.IFNZ NDHUN
	CMP I,#NLDHTY			;IGNORE NON-EXISTENT LINES
	BHI 4$
.ENDC
	CALL XMTDON
4$:	SUB #2,I
	CMP I,DHTYNO(H)
	BGE 2$
DHOEX:	POP <I,C,B,A,H>
	RTI

XMTDON:	TST TYPING(I)		;HERE WHEN OUTPUT FINISHES
	BGT 1$			;BRANCH IF -10 WANTS TO KNOW ABOUT IT
	BEQ 3$			;BRANCH IF NOTHING TO DO
	MOV #32,A		;SEND A CALL
	CALL RCV
	BR 3$

1$:	MOV I,A
	ASR A			;PUT TENNISH LINE NUMBER INTO RING
	MOV #TYORNG,B		;MAIN PROG LEVEL WILL LATER TELL -10
	CALL PUT
3$:	CLR TYPING(I)
	RET

.IFNZ NMPTYS	;OUTPUT DONE ON MULTIPLEXED LINE
MPXDON:	PUSH <C,D,H,I>
	TST MPXOAC
	BGE 1$
	NEG MPXOAC	;SENT HEADER, NOW SEND DATA
	MOV MPXOLN,A
	MOV MPXPNT(A),D
	MOV MPXNBT(A),C
	CLR MPXNBT(A)
	CALL @STROUT(H)	
	BR 9$

1$:	MOV MPXOLN,I	;OUTPUT IS DONE ON THAT LINE NOW
	ADD #NFMPTY,I
	CALL XMTDON
	CLR MPXOAC	;MPX IDLE
	CALL STRMPX	;LOOK FOR NEW STUFF TO DO
9$:	POP <I,H,D,C>
	RET
.ENDC ;NMPTYS

	.SBTTL DL11 INTERRUPTS

.REPT NDLS
CONC DL,\.RPCNT+1,<IBK: JSR H,DLIBK>
	NFDLHX+<2*.RPCNT>
CONC DL,\.RPCNT+1,<OBK: JSR H,DLOBK>
	NFDLHX+<2*.RPCNT>
.ENDR

DLIBK:	MOV (H),H		;GET HARDWARE INDEX OF INTERRUPTING UNIT
	PUSH <A,B,I>
	MOV @DLKB(H),A		;GET RECEIVED CHARACTER
	MOV DLTYNO(H),I		;GET LINE NUMBER RECEIVED ON
.IFNZ DTE20P
	BNE 2$			;ONLY T00 CAN RETURN TO KLDCP
	BIT #20000,A		;IF BREAK KEY IS HIT
	BEQ 1$
	SETOM KLDCPF		;USER WANTS TO RETURN TO KLDCP
	BR DLBKEX		;FOR ONE COMMAND LINE

1$:	TST DDTMOD		;IF IN DDT MODE,
	BEQ 2$
	BIC #-200,A		; HANDLE INPUT DIFFERENTLY
	MOV A,DDTCHR
	BR DLBKEX

2$:
.ENDC ;DTE20P
	CALL @TTYIPC(I)
DLBKEX:	POP <I,B,A,H>
	RTI

DLOBK:	MOV (H),H		;GET HARDWARE INDEX OF INTERRUPTING UNIT
	TST DLOAC(H)
	BEQ DLBKX1		;NOT SUPPOSED TO BE TYPING OUT, IGNORE INT
	DEC DLBC(H)		;GOT ANY MORE CHARACTERS?
	BLT DLBKX2		;NO, GO GIVE OUTPUT DONE
	MOV DLCA(H),-(SP)	;YES, GIVE NEXT CHARACTER
	MOVB @(SP)+,@DLPB(H)
	INC DLCA(H)
DLBKX1:	POP H
	RTI

DLBKX2:	PUSH <A,B,I>		;OUTPUT DONE
	MOV DLTYNO(H),I		;GET TTY INDEX OF INTERRUPTING LINE
	CLR DLOAC(H)		;OUTPUT NO LONGER ACTIVE ON THIS LINE
	CALL XMTDON
	BR DLBKEX

	.SBTTL CLOCK INTERRUPT

;NOTE - IT IS IMPORTANT THAT THIS BE AT A HIGHER INTERRUPT LEVEL THAN THE CHAOS NET
CLKBRK:	SETOM WAKE		;WAKE UP MAIN LOOP
.IFNZ GOULDP
	PUSH @#PS		;CHECK GOULD LPT
	CALL GLPBRK		;(LOSES INTERRUPTS)
	DEC GLPTIM		;TIME TO CHECK GOULD LPT?
	BGT 13$			;NOT YET
	MOV #10.*60.,GLPTIM
	BIT #%GSNRD,@#GLPCSR	;YES, LOSING?
	BNE 14$			;PROBABLY
	CLR GLPERR		;PROBABLY NOT
	BR 13$			;(CAN'T TELL FOR SURE IF %GCON NOT DONE)

14$:	MOV @#GLPCSR,GLPERR	;LPT LOSING, TELL 10
	CALL GLPRST		;AND MAKE SURE BUFFERS DON'T CHOKE UP
.ENDC ;GOULDP
13$:	PUSH <A,B,I>
.IFNZ NDMS	;MODEM SCANNER GETS SHUT OFF SOMEHOW
	CLR A	;loop over the DM11s, turning them on
	MOV #NDMS,B
259$:	BIT #DMSCN,@DMCSR(A)
	BEQ 14$
	BIT #DMIEN,@DMCSR(A)
	BNE 15$	
14$:	MOV #DMSCN+DMIEN,@DMCSR(A)	;ENABLE SCANNER INTERRUPTS
15$:	TST (A)+			;next DM11
	SOB B,259$		;until all DM11s done

.ENDC ;NDMS
.IFNZ CHAOSP	;WAKE-UP OUTPUT LINKS IN RE-TRANSMIT DELAY
	MOV #CHXCHS,I
50$:	MOV CHOHWR(I),A		;ADDRESS OF HARDWARE CSR
	TST CHOSTS(I)		;IF ZERO, IS IDLE, DON'T WANT INTERRUPT ENABLE
	BEQ 51$			;NOTE THAT THIS RUNS MASKED HIGHER THAN CHAOS INT LVL
	BIS #%CATEN,(A)		;RE-ENABLE INTERRUPT IF OFF
51$:
.IFNZ CHSBTB
	BIT #%CATDN,(A)		;TRANSMIT-DONE?
	BNE 59$
	INC CHSIDL(I)		;NO, KEEP TIME-OUT
	CMP CHSIDL(I),#60.	;IF TRANSMIT-DONE STUCK OFF FOR 1 SECOND,
	BLO 59$
	MOV #%CARST,(A)		; THEN RESET THE INTERFACE
;	MOV #%CAREN+%CATEN,(A)	;INTERRUPT ENABLES WILL TURN THEMSELVES BACK ON IF NECESSARY!
	INC CHSRST(I)		;COUNT NUMBER OF TIMES HAD TO DO THIS
59$:
.ENDC ;CHSBTB
.IFG CHAOSP-1
	TST (I)+
	CMP I,#CHXCHS+CHAOSP+CHAOSP
	BLO 50$
.ENDC ;CHAOSP-1
	DEC PULSAR		;TIME TO GENERATE TEST PACKET TO CHAOS NET?
	BGT 66$			;NOT YET
	MOV PULSON,PULSAR	;RE-INITIALIZE COUNTER
.REPT CHAOSP			;YES, AWAKEN ALL TRANSMIT INTERRUPT SIDES
	BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT>
.ENDR
.IFNZ TEN11P
	TST CHOSTS+CHXT11	;AWAITING BUFFER FROM 10?
	BNE 65$			;YES, COUNT TIMEOUT
	CLR T11TIM		;NO, RESET TIMEOUT
65$:	INC T11TIM
.ENDC ;TEN11P
66$:	DEC 4SEC		;TIME FOR 4-SECOND CLOCK?
	BGT 90$
	MOV #4*60.,4SEC		;YES
	MOV #<NSUBNT-1>*2,I	;INCREMENT ROUTING COSTS
71$:	TST SBNTYP(I)		;THIS GUY'S COSTS SUPPOSED TO INCREMENT?
	BNE 72$			;NOPE
	CMP SBNCST(I),#1000	;DON'T INCREMENT TOO HIGH AND OVERFLOW
	BHIS 72$
	INC SBNCST(I)		;YEP
72$:	SUB #2,I
	BPL 71$
	DEC 15SEC		;TIME FOR 15-SECOND CLOCK? (REALLY 16)
	BGT 90$
	MOV #4,15SEC		;YES
.REPT CHAOSP			;TELL CABLES TO BROADCAST %CORUT PACKETS
	SETOM CHXRTF+CHXCHS+<2*.RPCNT>
	BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT>
.ENDR
.IIF NZ ETHERP, SETOM CHXRTF+CHXETH	;TELL ETHERNET TO BROADCAST ROUTING
90$:				;CAN'T DO IT NOW BECAUSE WRONG INTERRUPT LEVEL
.ENDC ;CHAOSP
.IF DF NDVRBF
	INC DVRTIM		;TIME OUT DOVER CONNECTION
	CMP DVRTIM,#15.*60.	;IF IDLE FOR 15 SECONDS, FLUSH
	BLO 15$
	CLR DVRHST
	CLR DVRMSK
15$:	INC DVRRTR		;COUNT UP RETRANSMISSION COUNTER
.ENDC ;NDVRBF
.IFNZ NDMS			;GOT ANY TTYS WITH MODEM CONTROL?
	MOV #NFTTY,I		;CHECK FOR HANGUPS
16$:	TST DIALED(I)		;HANGUP IN PROGRESS ON THIS LINE?
	BPL 17$			;NO
	INC DIALED(I)		;YES, TIMED OUT?
	BMI 17$
	CLR DIALED(I)		;YUP, LINE IS HUNG UP
	MOV I,A			;TELL -10 ABOUT IT
	ASR A
	TST TTYHNG(I)		;IF THIS IS NEW STATUS FOR 10,
	BNE 18$
	INC HNGSIG		;INDICATE STATUS WAITING
18$:	MOV A,TTYHNG(I)		;SAVE THIS LINE'S LATEST STATUS
17$:	ADD #2,I
	CMP I,#LASTTY
	BLO 16$
.ENDC ;NDMS
	POP <I,B,A>

	ROR SWR			;LOW BIT OF SWITCHES => DDT
	BCC CLKEX
	BPT
CLKEX:	RTI
.IFNZ NDMS
	.SBTTL MODEM CONTROL

;;; hack multiple DM interrupt vectors
.REPT NDMS
CONC DM,\.RPCNT+1,<BRK: JSR H,DMBRK>
	2*.RPCNT
.ENDR ;NDMS


DMBRK:	PUSH <A,B,I>
	MOV (H),A			;get the device offset in A
	MOV @DMCSR(A),I			;GET ASSOCIATED TTY INDEX
	BIC #177760,I			;gives us channel (0-17) on this DM11
	;; now add <device # * 16.> to get offset into table for any DM
	MOV A,B				;device offset in B, is 2*device number
	ASL B
	ASL B
	ASL B				;multiply by 8 for offset in B
	ADD B,I				;add to I for offset for this channel
	ASL I				;now get word offset in I by shifting
	;; get index into map between DM channels and TTY indices
	MOV M2LMAP(I),I
	BEQ 90$				;EXIT IF THIS LINE NOT UNDER MODEM CONTROL
;	TST @DMCSR(A)	.SEE DMRNG
;	BPL 10$
;	TST DIALED(I)			;RINGING.  IS LINE DIALED UP ALREADY?
;	BNE 10$				;YES, NOT SUPPOSED TO BE RINGING
;	MOV #LINENB+LINDTR,@DMLSR(A)	;ANSWER THE PHONE

10$:	BIT #LINCTS,@DMLSR(A)		;DO WE HAVE CLEAR-TO-SEND?
	BEQ 20$				;NO
	TST DIALED(I)			;YES, WHAT WAS PREVIOUS STATE?
	BEQ 13$				;WAS OFF, THIS IS A DIALUP
	BPL 90$				;WAS ON, IGNORE
	NEG DIALED(I)			;WAS HANGING UP, ABORT IT
	BR 90$

13$:	INC DIALED(I)			;LINE IS NOW DIALED UP
	TST DMINI			;IF GETTING INITIAL STATE,
	BNE 90$				;DON'T HACK AUTOSPEED
	TST AUTOSP(I)			;IF IT HAS AUTOSPEED,
	BEQ 90$
	MOV HDWR(I),H			;HACK THAT
	CALL ASPMD
	BR 90$

20$:	TST DIALED(I)			;CTS DROPPED
	BMI 90$				;ALREADY KNOWN ABOUT, IGNORE
	MOV #-HNGDLY,DIALED(I)		;OTHERWISE START HANGUP TIMEOUT

90$:	BIC #DMDON,@DMCSR(A)		;RESTART SCANNER
	POP <I,B,A>
	POP H
	RTI
.ENDC ;NDMS

.IFNZ GOULDP
.SBTTL GOULD PRINTER P.I. LEVEL

GLPBRK:	BIT #%GSBSY,@#GLPCSR
	BEQ 1$
	RTI				;LPT BUSY, WAIT

1$:	BIT #%GSDON,@#GLPCSR
	BNE 2$
	RTI				;LPT BUSY OTHER FLAVOR

2$:	PUSH <A,B,H>
	BIT #%GSERR,@#GLPCSR		;LPT LOSING?
	BEQ GLPBR1
	CALL GLPRST			;YUP, RESET THE BUFFERS
	MOV @#GLPCSR,GLPERR		;AND TELL 10

GLPOFF:	CLR GLPOAC			;HERE TO STOP P.I.
	MOV #%GCIOF,@#GLPCSR
	MOV #5000.,A			;LPT SOMETIMES BUSY FOR A WHILE
1$:	BIT #%GSBSY,@#GLPCSR		;HAVE TO WAIT SO TONER PUMPS WILL
	BEQ 2$				;REALLY TURN OFF
	SOB A,1$
2$:	MOV #%GCOFF,@#GLPCSR
GLPEX:	POP <H,B,A>
	RTI

GLPFIN:	MOV #%GBIDL,GB.STA(H)		;DONE WITH THIS BUFFER
	MOV GB.NXT(H),H			;CHECK NEXT
	MOV H,GLPOOP

GLPBR1:	MOV GLPOOP,H			;CHECK ON BUFFERS
	CMP GB.STA(H),#%GBDMA		;FINISH DMA XFER?
	BEQ GLPFIN			;YES
	CMP GB.STA(H),#%GBWRT		;QUEUED OR ALREADY ACTIVE AT P.I.?
	BLT GLPOFF			;NO, STOP
	MOV #%GBPI,GB.STA(H)		;YES, ACTIVATE IT AT P.I.
	TST GB.FF(H)			;NEED FF?
	BEQ 1$
	MOV #%GCFF,@#GLPCSR		;YES
	CLR GB.FF(H)
	BR GLPEX

1$:	TST GB.NL(H)			;NEED BLANK LINES?
	BEQ 2$
	DEC GB.NL(H)			;YES, GIVE ONE
	MOV #%GCADV,@#GLPCSR
	BR GLPEX

2$:	MOV H,B				;SET UP TEXT ADDR
	ADD #GB.DAT,B
	MOV GB.PNT(H),A			;SET UP TEXT WORD COUNT
	NEG A
	MOV A,@#GLPWC
	MOV B,@#GLPCA			;START XFER
	MOV #%GBDMA,GB.STA(H)		;FLAG BUFFER ACTIVE AT DMA LEVEL
	BR GLPEX

GLPRST:	PUSH H
	MOV #GLPBFF,H			;FLUSH ALL BUFFERS
	MOV H,GLPOOP
	MOV H,GLPOIP
3$:	CLR (H)+
	MOV (H),H
	CMP H,#GLPBFF
	BNE 3$
	MOV #60.*10.,GLPTIM		;SET TIMEOUT
	POP H
	RET

.ENDC ;GOULDP

.IFNZ CHAOSP

	.SBTTL CHAOSNET ROUTINES

;ALL ROUTINES ON THIS PAGE CALLED WITH INTERRUPTS MASKED, INDEX IN I.

;REFILL FROM CHAOS INTERFACE
CHSRFL:	BIS #%CAREN,@CHIHWR(I)	;TURN ON RECEIVER INTERRUPTS
	RET			;WILL NOTICE INPUT LATER

.IFNZ DL10P
;LOOPS BACK TO HERE WHEN DISCARDING A PACKET
DLCRF1:	CMP (SP)+,(SP)+		;POP <D,H>
	POP A
	INC DLCSS1(A)		;2 ;INDICATE BUFFER HAS BEEN COPIED
	BIS #DLX10I,DLXCSR	;AND INTERRUPT THE PDP10
				;DROP INTO DLCRFL
;REFILL FROM DL10
DLCRFL:	CALL DLCCHK		;SEE IF DL10 IS DISABLED
	BNE 99$			;BRANCH IF YES
	MOV #2,A		;CHECK BOTH 10 TO 11 BUFFERS SO CAN'T GET OUT OF PHASE WITH 10
10$:	CMP DLCSS1(A),#1	;10 SAYS BUFFER READY?
	BEQ 11$			;YES
	SUB #2,A		;NO, TRY NEXT
	BPL 10$
	BR 99$			;NONE READY

11$:	PUSH A			;SAVE CURRENT 10 TO 11 BUFFER
	ADD #DLCSP1,A		;OUTPUT READY, GET IT
	MOV #DLCIBF,B		;COPY INTO BUFFER
.REPT PKHDW			;FIRST GET HEADER
	MOV (A),(B)+
.ENDR
	PUSH <A,B>
	CALL CHSIHD		;PROCESS HEADER, GET LENGTH, DEST
	BVS DLCRF1		;BRANCH IF PACKET NO GOOD
	POP <D,H>
	PUSH C
	SUB CHIHDL(I),C		;GET NUMBER OF DATA WORDS TO FOLLOW
	CALL MOVHD		;MOVE THOSE WORDS
	POP <C,A>		;RESTORE LENGTH, 10 TO 11 BUFFER NUMBER
	INC DLCSS1(A)		;2 ;INDICATE BUFFER HAS BEEN COPIED
	BIS #DLX10I,DLXCSR	;AND INTERRUPT THE PDP10
	TST B			;SWAB IF NOT TO 10-COMPATIBLE DEST
	CALL SWAB10
	INC CHISTS(I)		;INDICATE BUFFER READY TO SEND
99$:	RET

;TRANSMIT TO DL10 OUTPUT SINK
;REQUIRES I TO BE SET UP, SMASHES ALL REGS.
DLCXMT:	CALL DLCCHK		;DL10 DISABLED?
	BNE 70$			;YES, DISCARD PACKET
	MOV DLCRBN,A		;GET CURRENT 11 TO 10 BUFFER NUMBER
	CMP DLCRS1(A),#1	;BUFFER READY?
	BNE 80$			;NO, WAIT
	MOV CHOINX+CHXDLC,D	;GET ADDRESS OF BUFFER TO BE SENT OVER
	MOV CHILNG(D),C		;AND LENGTH
	MOV CHIBFP(D),D
	MOV A,H			;GET POINTER TO DL10 MAGIC IDPB WORD
	ADD #DLCRP1,H
	CALL MOVDH		;COPY WORDS INTO PDP10
	INC DLCRS1(A)		;SIGNAL DATA AVAILABLE TO PDP10
	BIS #DLX10I,DLXCSR	;AND INTERRUPT IT
	MOV DLCNXT(A),DLCRBN	;SWITCH BUFFERS
70$:	JMP CHSODN		;TRANSMISSION IS DONE ALREADY

80$:	MOV #1,CHOSTS+CHXDLC	;TRANSMISSION AWAITING BUFFER FROM 10
	RET

;CALL HERE WHEN DL10 INTERRUPTS, CLOBBERS ALL.
DLCWAK:	MASK 5
	TST CHOSTS+CHXDLC	;DL10 HUNG ON TRANSMIT?
	BEQ 10$
	MOV #CHXDLC,I		;YES, WAKE IT UP
	CALL DLCXMT
10$:	TST CHISTS+CHXDLC	;DL10 INPUT ACTIVE?
	BNE 20$
	MOV #CHXDLC,I		;NO, TRY TO GET SOME
	CALL DLCRFL
	TST CHISTS(I)		;GOT SOME?
	BLE 20$
	CALL CHSOUT		;YES, START TRANSMISSION
20$:	CALL CHSRUN		;DO ANYTHING ELSE REQUIRED
	UNMASK
	RET

;RETURN 'NE' IF DL10 IS DISABLED, BASHES NOTHING.
DLCCHK:	TST DLXOFF
	BNE 99$
	TST NO.ITS
	BNE 99$
	TST DLCINI		;RE-INITIALIZE?
	BEQ 99$			;NO, EVERYTHING IS OK.
	CLR DLCRBN		;YES
	TST CHOSTS+CHXDLC	;WAS OUTPUT HUNG ON DL10?
	BEQ 90$
	PUSH <A,B,C,D,I,H>	;YES, SIGNAL OUTPUT DONE ON DL10
	MOV #CHXDLC,I
	CALL CHSODN
	POP <H,I,D,C,B,A>
90$:	CLR DLCINI		;SIGNAL INIT DONE, RETURN 'EQ'
99$:	RET
.ENDC ;DL10P

;FAST BLOCK MOVE
;THESE CAN MOVE AT MOST 256. WORDS

;MOV (H),(D)+
;SOB C,.-2
MOVHD:	SUB #256.,C		;GET -#WDS LESS THAN MAXIMUM
	ADD C,C			;CONVERT TO BYTES
	SUB C,PC		;JUMP INTO MOVE TABLE
	.REPT 256.
	MOV (H),(D)+
	.ENDR
	RET

;MOV (D)+,(H)
;SOB C,.-2
MOVDH:	SUB #256.,C		;GET -#WDS LESS THAN MAXIMUM
	ADD C,C			;CONVERT TO BYTES
	SUB C,PC		;JUMP INTO MOVE TABLE
	.REPT 256.
	MOV (D)+,(H)
	.ENDR
	RET

.IFNZ TEN11P
;REFILL FROM TEN-11 INTERFACE
T11RFL:	CALL T11CHK		;CHECK FOR DISABLE
	BNE 99$			;BRANCH IF DISABLED
	MOV T11IBP,A
	TST T11IBA		;WAS INPUT BUFFER IN USE?
	BEQ 10$
	CLR (A)+		;YES, INDICATE BUFFER IS NOW EMPTY
	CLR (A)
	CLR T11IBA
	ADD #T11BFL-2,A		;ADVANCE POINTER
	CMP A,#T11IBE
	BLO 7$
	MOV #T11IBF,A
7$:	MOV A,T11IBP
10$:	TST (A)			;INPUT BUFFER CONTAIN A PACKET?
	BEQ 99$			;NO
	SETOM T11IBA		;YES, INPUT BUFFER NOW ACTIVE
	ADD #8,A		;GET INPUT FROM PDP10
	MOV A,CHIBFP+CHXT11	;AS CURRENT INPUT BUFFER
	CALL CHSIHD		;PROCESS THE HEADER
	BVS T11RFL		;BRANCH IF PACKET NO GOOD
	PUSH <A,B,C,H>		;COMPUTE CHECKSUM BEFORE SWABBING
	INC C			;C GETS NUMBER OF 32-BIT WORDS
	ASR C
	CLR D			;CLEAR LOW WORD OF CHECKSUM
	CLR H			;CLEAR HIGH WORD OF CHECKSUM
	SUB #PKFCMS+1,PKFC(A)	;DECREMENT FWD COUNT (IS HIGH END OF WORD)
				;FWD COUNT HAS TO BE PUT BACK FOR CHECKSUM COMPUTATION
21$:	ADD (A)+,H		;ADD HIGH HALFWORD TO HIGH SUM
	ADD (A)+,D		;ADD LOW HALFWORD TO LOW SUM
	ADC H			;CARRY INTO HIGH SUM
	MOV D,B			;NOW ROTATE RIGHT DOUBLE
	ROR B
	ROR H
	ROR D
	SOB C,21$
	MOV T11IBP,A		;NOW COMPARE CHECKSUM
	CMP H,4(A)
	BNE 30$
	CMP D,6(A)
	BNE 30$	
	POP <H,C,B,A>
	ADD #PKFCMS+1,PKFC(A)	;INCREMENT FWD COUNT (IS HIGH END OF WORD)
	TST B			;SWAB IF NOT TO 10-COMPATIBLE DEST
	CALL SWAB10
	INC CHISTS(I)		;INDICATE BUFFER READY TO SEND
99$:	RET

30$:	POP <H,C,B,A>		;CHECKSUM ERROR
	INC T11CKE		;COUNT CHECKSUM ERRORS
	BR T11RFL		;AND IGNORE PACKET

;TRANSMIT TO TEN11 OUTPUT SINK
;REQUIRES I TO BE SET UP, SMASHES ALL REGS.
T11XMT:	CALL T11CHK		;TEN11 DISABLED?
	BNE 70$			;YES, DISCARD PACKET
	TST @T11OBP		;OUTPUT BUFFER EMPTY?
	BNE 80$			;NO, WAIT
	MOV CHOINX+CHXT11,D	;GET ADDRESS OF BUFFER TO BE SENT OVER
	MOV CHIBFP(D),B
	MOV CHILNG(D),C		;AND LENGTH
	MOV PKNBYT(B),A
	BIT #1,A		;IF ODD NUMBER OF BYTES, CLEAR THE EXTRA ONE
	BEQ 5$
	BIC #PKNBMS,A
	ADD B,A
	CLRB PKDAT-1(A)		;NOTE, AT THIS POINT BYTES ARE SWAPPED
5$:	MOV T11OBP,A		;COPY INTO TEN11 OUTPUT BUFFER
	ADD #8,A
	PUSH <H,C>
10$:	MOV (B)+,(A)+
	SOB C,10$
	MOV (SP),C		;NOW COMPUTE CHECKSUM
	INC C			;C GETS NUMBER OF 32-BIT WORDS
	ASR C
	BCS 11$
	CLR (A)+		;IF ODD NUMBER OF 16-BIT WORDS, CLEAR THE EXTRA ONE
11$:	CLR D			;CLEAR LOW WORD OF CHECKSUM
	CLR H			;CLEAR HIGH WORD OF CHECKSUM
	MOV T11OBP,A
	ADD #8,A
21$:	ADD (A)+,H		;ADD HIGH HALFWORD TO HIGH SUM
	ADD (A)+,D		;ADD LOW HALFWORD TO LOW SUM
	ADC H			;CARRY INTO HIGH SUM
	MOV D,B			;NOW ROTATE RIGHT DOUBLE
	ROR B
	ROR H
	ROR D
	SOB C,21$
	MOV T11OBP,A		;STORE CHECKSUM INTO OUTPUT BUFFER
	MOV H,4(A)
	MOV D,6(A)
	POP <C,H>
	SETOM (A)		;SIGNAL PRESENCE OF PACKET TO PDP10
	ADD #T11BFL,A		;ADVANCE POINTER
	CMP A,#T11OBE
	BLO 30$
	MOV #T11OBF,A
30$:	MOV A,T11OBP
70$:	CLR T11TIM		;NO TIMEOUT, 10 IS TAKING PACKETS
	JMP CHSODN		;TRANSMISSION IS DONE ALREADY

80$:	MOV #1,CHOSTS+CHXT11	;TRANSMISSION AWAITING BUFFER FROM 10
	RET

;WHACK YOUR TEN11
T11WAK:	MASK 5
	MOV #CHXT11,I
	CALL T11CHK		;IS 10 UP?
	BNE 30$			;IT'S DOWN, PUNT IT
	TST CHOSTS(I)		;TEN11 HUNG ON TRANSMIT?
	BEQ 10$
	CALL T11XMT		;YES, WAKE IT UP
10$:	TST CHISTS+CHXT11	;TEN11 INPUT ACTIVE?
	BNE 20$
	MOV #CHXT11,I		;NO, TRY TO GET SOME
	CALL T11RFL
	TST CHISTS(I)		;GOT SOME?
	BLE 20$
	CALL CHSOUT		;YES, START TRANSMISSION
20$:	CALL CHSRUN		;DO ANYTHING ELSE REQUIRED
	UNMASK
	RET

30$:	TST CHOSTS(I)		;TRANSMITTING TO DEAD TEN-11?
	BEQ 20$
	CLR T11TIM		;YES, FLUSH IT
	CALL CHSODN
	BR 20$

;CHECK TEN-11 INTERFACE, DO RESET IF NECESSARY, RETURN 'NE' IF DISABLED.
;SMASHES NOTHING.
T11CHK:	CMP T11TIM,#5*60.	;10 TAKING 5 SECONDS TO RESPOND?
	BLO 5$
	SETOM T11I10		;YES, DECLARE IT DOWN, REINITIALIZE PROTOCOL
5$:	TST T11I10		;IS 10 DONE INITIALIZING?
	BNE 99$			;NO, DO NOTHING
	TST T11I11		;ARE WE SUPPOSED TO INITIALIZE?
	BEQ 99$			;NO, IT'S OK
	MOV #T11OBF,T11OBP	;YES, REINITIALIZE POINTERS
	MOV #T11IBF,T11IBP
	PUSH A
	MOV #T11OBF,A		;INITIALIZE INPUT AND OUTPUT BUFFER HEADERS
10$:	CLR (A)+		;CLEAR INTER-MACHINE SIGNAL WORD
	CLR (A)+
	ADD #T11BFL-4,A		;SKIP THE REMAINING WORDS
	CMP A,#T11IBE
	BLO 10$
	CLR T11IBA		;IDLE THE INPUT
	POP A
	TST CHOSTS+CHXT11	;WAS OUTPUT HUNG ON TEN11?
	BEQ 90$
	PUSH <A,B,C,D,H,I>	;YES, SIGNAL OUTPUT DONE ON TEN11
	MOV #CHXT11,I
	CALL CHSODN
	POP <I,H,D,C,B,A>
90$:	CLR T11I11		;SIGNAL INIT DONE, RETURN 'EQ'
	CLR T11I11+2
99$:	RET
.ENDC ;TEN11P

;THIS ROUTINE PROCESSES THE HEADER OF PACKET IN INPUT BUFFER FOR SOURCE I
;RETURN DESTINATION OUTPUT SINK INDEX IN B (-1 IF THIS IS FOR US (PDP11 ITSELF)),
;PACKET BUFFER POINTER IN A, AND LENGTH IN WORDS IN C.
;RETURNS WITH OVERFLOW SET IF PACKET IS DISCARDED BECAUSE OF
;TOO MUCH FORWARDING, BAD ADDRESS, TOO BIG, CRUFTY, ETC.
;OTHERWISE RETURNS WITH MINUS INDICATOR SET IF PACKET DIRECTED TO 11.
CHSIHD:	ADD #1,NPKSI(I)		;COUNT PACKETS IN FROM THIS SOURCE
	ADC HPKSI(I)
	MOV CHIBFP(I),A		;POINTER TO PACKET
	TSTB (A)		;CHECK FOR MUPPET
	BNE CHSIHB		;DISCARD, WE DON'T SUPPORT THEM
	MOV #PKHDW,CHIHDL(I)	;SET HEADER LENGTH
	ADD #PKFCMS+1,PKFC(A)	;INCREMENT FWD COUNT (IS HIGH END OF WORD)
	BCS CHSIHB		;BRANCH IF FORWARDING LOOP
	MOV PKNBYT(A),C		;GET BYTE COUNT
	BIC #PKNBMS,C
	CMP C,#DATMAX
	BHI CHSIHB		;TOO LONG, LOSES
	INC C			;MAKE WORD COUNT
	ASR C
	ADD CHIHDL(I),C		;ADD IN LENGTH OF HEADER
	MOV C,CHILNG(I)		;SAVE FOR LATER USE
	;; NOW ROUTE THIS PACKET
	MOV #-1,B		;MAGIC INDEX MEANING "MYSELF"
	MOV PKDHST(A),D		;GET DESTINATION ADDRESS
	;HERE WE HAVE HAIR FOR MULTIPLE CHAOSNETS
.REPT CHAOSP
   CONC <CMP D,#CHAD>,\.RPCNT	;ADDRESSED TO PDP11 ITSELF?
	BEQ 50$			;YES, LET CHSRUN HANDLE IT LATER
.ENDR ;CHAOSP
	CMPB PKOP(A),#%CORUT	;ROUTING INFO PACKET?
	BEQ 40$			;YES, ADDRESS TO PDP11
	TST USECBL		;SUPPOSED TO USE CABLE EVEN TO TALK TO SELF?
	BEQ 20$
	CMP I,#CHXCHS		;YES, IS THIS COMING FROM CABLE?
	BHIS 20$		;YES, ROUTE REGULAR WAY
	MOV #CHXCHS,B		;NO, SEND TO SELF ON FIRST CABLE
	MOV #CHAD0,D
	BR 39$

20$:	MOVB PKDHST+1(A),B	;GET SUBNET ADDRESSED TO
	CMP B,#NSUBNT
	BLO 21$
	CLR B			;OUT OF RANGE, USE 0
21$:	ASL B			;MAKE INDEX INTO SUBNET TABLES
	TST SBNTYP(B)		;IS THIS A DIRECT HARDWARE CONNECTION?
	BGT 38$			;YES, SEND TO IT
	MOV SBNADR(B),D		;NO, GO VIA GATEWAY
	BEQ CHSIRF		;HAVEN'T GOT A GATEWAY, AND BROADCAST CODE NOT WORKING YET
	MOVB SBNADR+1(B),B	;GET SUBNET GATEWAY IS ON
	ASL B			;MAKE INDEX INTO TABLES
	CMP B,#NSUBNT*2
	BHIS CHSIRF		;OUT OF RANGE, CAN'T GET THERE FROM HERE
	TST SBNTYP(B)		;IS THIS A DIRECT CONNECTION?
	BLE CHSIRF		;NO, CAN'T GET THERE FROM HERE (SHOULDN'T HAPPEN!)
38$:	MOV SBNADR(B),B		;GET SINK INDEX
39$:	MOV D,CHICBA(I)		;STORE CABLE ADDRESS OF IMMEDIATE DEST (GATEWAY)
.IIF NDF NDVRBF, 50$:		;IF NO DOVER, ALL TO-11 PACKETS COME HERE
40$:	MOV B,CHIOUX(I)		;STORE SINK INDEX, SET INDICATORS
	RET			;NOTE THAT MOV CLEARS OVERFLOW

.IF DF NDVRBF
50$:	CMP PKDIND(A),DVRLIX	;DIRECTED TO DOVER?
	BNE 40$			;NO, TO 11
	CMP PKSHST(A),DVRHST
	BNE 40$			;NOT DOVER-CONNECTED HOST
	CMP PKSIND(A),DVRIDX
	BNE 40$			;RIGHT HOST, WRONG PROCESS
	MOV #CHXDVR,B		;ROUTE PACKET TO DOVER GATEWAY
	BR 40$
.ENDC ;NDVRBF

;HERE FOR ROUTING FAILURE.  METER, RETURN WITH OVERFLOW SET.
CHSIRF:	INC NPKSRF
	MOV B,RFSBNT		;SAVE 2* SUBNET TRYING TO GET TO
	;FALL INTO CHSIHB
;HERE WHEN CHSIHD SEES A GARBAGE PACKET.  RETURN WITH OVERFLOW SET.
CHSIHB:	ADD #1,NPKSBD(I)	;GOD-DAMN BRAIN-DAMAGE
	ADC HPKSBD(I)
	SEV
	RET

;SWAB PACKET COMING FROM PDP-10 OR ETHERNET (BYTES LEFT TO RIGHT)
;IF GOING TO INCOMPATIBLE DESTINATION.  CALL RIGHT AFTER CHSIHD.
SWAB10:	BMI CHSSWB		;SWAB IF TO-11
	CMP CHOXMT(B),#CHSXMT	;CHECK DESTINATION TYPE
	BEQ CHSSWB		;PDP11 OR CHAOSNET, SWAB IT OUT
5$:	RET			;PDP10 OR ETHERNET, LEAVE ALONE

;SWAB PACKET COMING FROM PDP-11 OR CHAOSNET (BYTES RIGHT TO LEFT)
;IF GOING TO INCOMPATIBLE DESTINATION.  CALL RIGHT AFTER CHSIHD.
SWAB11=.
	BMI 5$			;RETURN IF TO-11
	CMP CHOXMT(B),#CHSXMT	;CHECK DESTINATION TYPE
	BEQ 5$			;PDP11 OR CHAOSNET, LEAVE ALONE
				;PDP10 OR ETHERNET, SWAB IT OUT
				;DROPS THROUGH INTO CHSSWB
;THIS ROUTINE SWABS THE PACKET FOR THE SOURCE IN I.
;CALLED WITH NUMBER OF WORDS IN PACKET IN C.
;CLOBBERS A, C, AND D.
;SUITABLE FOR CALLING RIGHT AFTER CHSIHD RETURNS.
CHSSWB:	MOV CHIBFP(I),A		;ADDRESS OF PACKET
	SUB CHIHDL(I),C		;GET LENGTH OF DATA AREA IN WORDS
	BLE 99$			;EMPTY
	MOVB PKOP(A),D		;GET OPCODE
	BPL 5$			;BRANCH IF NON-DATA
	BIT #100,D		;CHECK FOR BINARY DATA
	BEQ 10$			;NO, GO SWAB
99$:	RET

5$:	TSTB CHSBIN(D)		;CONTROL, LOOK UP OPCODE
	BNE 99$			;BINARY, NO SWAB
10$:	ADD CHIHDL(I),A		;POINT TO DATA AREA OF BUFFER
	ADD CHIHDL(I),A		;BYTES, WATSON, BYTES!
	SUB #PKTMXW,C		;GET -#WDS LESS THAN MAXIMUM
	ADD C,C			;CONVERT TO BYTES
	SUB C,PC		;JUMP INTO SWAB TABLE
	.REPT PKTMXW
	SWAB (A)+
	.ENDR
	RET

;BYTE TABLE INDEXED BY OPCODE, NON-ZERO IF BINARY
;BINARY OPERATIONS ARE 2 (%COOPN), 7 (%COSTS), 10 (%CORUT)
CHSBIN:	.BYTE 0,0,2,0,0,0,0,7,10,0,0,0,0,0
	.BYTE 0,0		;SPARES IN CASE MORE OPCODES ADDED
	.EVEN

;TRANSMIT PACKET FROM INPUT SOURCE I TO OUTPUT SINK, IN B.
;SMASHES ALL REGISTERS.  CHISTS(I), CHIOUX(I), CHICBA(I) MUST BE ALREADY SET UP.
CHSOUT:	TST B			;THIS DESTINED TO PDP11?
	BMI CHSOUX		;YES, LET CHSRUN PICK IT UP LATER
	TST CHOSTS(B)		;IS SINK BUSY?
	BNE CHSOUX		;YES, CAN'T SEND NOW, WILL TRY AGAIN LATER
	NEG CHISTS(I)		;NO, SET SOURCE STATUS TO CONNECTED
	MOV I,CHOINX(B)		;CONNECT SINK TO SOURCE
	MOV B,I			;SET UP SINK INDEX
	ADD #1,NPKSO(I)
	ADC HPKSO(I)
	JMP @CHOXMT(I)		;GO START TRANSMISSION TO SINK

;CALL HERE WHEN OUTPUT IS DONE ON SINK I.
CHSODN:	CLR CHOSTS(I)		;IDLE THE SINK
	PUSH I
	MOV CHOINX(I),I		;GET CORRESPONDING SOURCE
	CLR CHISTS(I)		;IDLE IT
	CALL @CHIRFL(I)		;TELL SOURCE IT'S DONE, TRY TO GET MORE INPUT
	POP I
CHSOUX:	RET

;CALL HERE AFTER EACH PACKET TRANSFER TO INITIATE AS MANY ADDITIONAL TRANSFERS
;AS POSSIBLE.  BASHES ALL REGISTERS.  ON DL10 AND TEN11, WE COULD ACTUALLY DO SEVERAL
;TRANSFERS BEFORE RETURNING.
CHSRUN:
.IF DF NDVRBF
	CALL DVRRFL		;WAKE UP DOVER, MIGHT BE TIME TO RETRANSMIT
.ENDC ;NDVRBF
	MOV #<NCHX-1>*2,I	;SCAN ALL INPUT SOURCES
CHSRN1:	TST WAKE		;GIVE UP IF CLOCK HAS TICKED, LET TTYS RUN
	BNE CHSOUX
	TST CHISTS(I)		;IS THIS SOURCE LOOKING FOR A SINK?
	BLE CHSRN3
CHSRN2:	MOV CHIOUX(I),B		;GET SINK IT WANTS TO SEND TO
	BMI FOR11		;BRANCH IF FOR PDP11
	TST CHOSTS(B)		;SINK AVAILABLE?
	BNE CHSRN3		;NO, LET INPUT SIT
	CALL CHSOUT		;YES, ATTEMPT TO TRANSMIT
	BR CHSRUN		;LOOK FOR MORE WORK

CHSRN3:	SUB #2,I		;NEXT INPUT SOURCE
	BGE CHSRN1
	RET			;NOTHING LEFT TO DO

FOR11:	MOV CHIBFP(I),A		;PACKET FOR PDP11, CHECK IT OUT
	MOVB PKOP(A),B		;GET OPCODE
	CMP B,#%CORUT		;IF ROUTING INFO, GOBBLE IT
	BEQ CHARUT
	CMP B,#%CORFC		;ALL WE KNOW IS RFC TO CERTAIN CONTACT NAMES
	BNE FOR11J		;BARF AT JUNK PACKETS
	CALL SERVE		;RUN THE SERVER
	BEQ FOR11X		;IT DIDN'T LIKE IT
FOR11R:	PUSH <PKDHST(A),PKDIND(A)>	;INTERCHANGE SOURCE AND DESTINATION
	MOV PKSHST(A),PKDHST(A)
	MOV PKSIND(A),PKDIND(A)
	POP <PKSIND(A),PKSHST(A)>
	CALL CHSIHD		;ROUTE
	BVS FOR11X		;NO GOOD, FLUSH (SOURCE IN PACKET WAS WRONG)
	CALL SWAB11		;SWAB IF GOING TO 11-INCOMPATIBLE DEST
	BR CHSRN2		;FIRE IT OFF (CHISTS IS ALREADY 1)

FOR11X:	CLR CHISTS(I)		;DISCARD THIS PACKET
	CALL @CHIRFL(I)
	BR CHSRUN		;LOOK FOR MORE WORK

;PACKET FROM RANDOM PLACE DIRECTED TO 11, TELL HIM TO GO AWAY
FOR11J:	CMP B,#%COLOS		;DON'T BARF AT LOS PACKETS
	BEQ FOR11X
	MOV #<%COLOS*400>,(A)
	MOV #6$-5$-1,PKNBYT(A)
	MOV #5$,B
	MOV A,C
	ADD #PKDAT,C
1$:	MOVB (B)+,(C)+
	BNE 1$
	BR FOR11R		;SEND OFF THE LOS
5$:	.ASCIZ /Packet unrecognized by gateway-11/
6$:	.EVEN

;ROUTING PACKET
CHARUT:	MOV CHILNG(I),C		;GET NUMBER OF DATA WORDS
	SUB #PKHDW,C
	ASR C			;MAKE NUMBER OF 2 WORD PAIRS
	BEQ FOR11X		;MIGHT BE ZERO-LENGTH
	MOV A,D
	ADD #PKDAT,D		;POINT TO START OF PACKET'S DATA
61$:	MOV (D)+,B		;GET SUBNET BEING TALKED ABOUT
	CMP B,#NSUBNT		;ONE WE KNOW ABOUT?
	BHIS 62$		;NO, FORGET IT
	ASL B			;MAKE WORD INDEX
	TST SBNTYP(B)		;IS THIS AN AUTO ROUTING TYPE SUBNET?
	BNE 62$			;NO, DON'T MUNG OUR FIXED ROUTING INFO
	CMP (D),SBNCST(B)	;COMPARE COSTS
	BHI 62$			;NEW ONE WORSE (IF EQUAL, SWITCH TO EQUALIZE LOAD)
	MOV (D),SBNCST(B)	;SAVE BEST COST
	MOV PKSHST(A),SBNADR(B)	;AND HOST ADDRESS THIS CAME FROM AS BEST BET
62$:	TST (D)+		;SKIP COST
	SOB C,61$
	BR FOR11X		;DONE WITH PACKET

	.SBTTL CHAOS NET SERVERS

;CALLED WITH PACKET IN A.
;MUST PRESERVE A,I.
;RETURN 'EQ' IF NO GOOD, 'NE' IF MODIFIED PACKET TO BE RETURNED TO SOURCE

;CURRENTLY WE SERVE THE FOLLOWING CONTACT NAMES:
; STATUS - RETURNS ANS WITH THE NAME OF THE MACHINE, LATER WILL HAVE OTHER DATA
; PULSAR - RETURNS ANS WITH DATA OF 1 BYTE, VALUE OF PULSON AS AN ASCII DIGIT,
;	   I.E. "0" MEANS OFF, "1" MEANS 60 PER SECOND, ETC.
;	   IF CONTACT NAME IN RFC IS FOLLOWED BY A SPACE AND AN ASCII DIGIT,
;	   SETS PULSON TO THAT STATUS.
; DOVER - DOVER PROTOCOL TRANSLATOR

;NOTE THAT WE DON'T USE THE MOST WINNING STRING COMPARE IN THE WORLD,
;THIS CODE ASSUMES IT DOESN'T MATTER WHAT HAPPENS IF AN RFC TO
;AN UNKNOWN CONTACT NAME IS DONE, AS LONG AS THE 11 DOESN'T CRASH.

SERVE:	MOV #SRVTBL,B		;ADDRESS OF SERVER TABLE
10$:	MOV (B)+,D		;ADDRESS OF CONTACT NAME FOR THAT SERVER
	BEQ 99$			;EXIT IF TABLE EXHAUSTED, 'EQ' IN COND CODE
	MOV A,C
	ADD #PKDAT,C		;ADDRESS OF CONTACT NAME IN THIS RFC
11$:	TSTB (D)		;END OF STRING?
	BEQ 20$			;YUP, RUN THIS SERVER
	CMPB (C)+,(D)+		;DO STRING COMPARE
	BEQ 11$			;MATCHES
	TST (B)+		;DOESN'T MATCH, TRY NEXT
	BR 10$

99$:	RET

20$:	JMP @(B)+		;CALL SERVER, IT CAN RETURN EQ OR NE

SRVTBL:	.WORD 1$,STSSRV		;STATUS - RETURN HOST NAME AND METERS
	.WORD 2$,PLSSRV		;PULSAR - SET AND GET PULSAR RATE
.IIF DF NDVRBF, .WORD 3$,DVROPN	;DOVER - DOVER PROTOCOL TRANSLATOR
	.WORD 0			;END OF TABLE
1$:	.ASCIZ /STATUS/
2$:	.ASCIZ /PULSAR/
3$:	.IIF DF NDVRBF, .ASCIZ /DOVER/
	.EVEN

;SERVERS MUST PRESERVE A (PACKET), AND I, AND RETURN 'NE' IF TO BE SENT BACK TO SOURCE.
;NOTE THAT C POINTS AT THE NEXT BYTE AFTER THE CONTACT NAME

STSSRV:	MOV A,B		;RFC TO "STATUS", CHANGE INTO ANS CARRYING APPROPRIATE DATA.
	MOV #32.+<12.*NCHX>+<24.*CHAOSP>+<12.*ETHERP>,PKNBYT(A) ;SET BYTE LENGTH, CLEAR FORWARDING COUNT
	ADD #PKDAT,B
	MOV #HSTNAM,D		;SEND NAME OF HOST
	MOV #32.,C
45$:	MOVB (D)+,(B)+
	SOB C,45$
	CLR D			;NOW STORE METERING INFO FOR EACH SUBNET
50$:	MOV CHXSBN(D),(B)+	;STORE SUBNET NUMBER+400
	MOV #4,(B)+		;ASSUME NOT A CABLE
	MOV NPKSI(D),(B)+
	MOV HPKSI(D),(B)+
	MOV NPKSO(D),(B)+
	MOV HPKSO(D),(B)+
.IFNZ ETHERP
	CMP D,#CHXETH		;ETHERNET HAS SOME OF THESE COUNTERS
	BNE 55$
	MOV #12.,-10.(B)	;THERE ARE 4 MORE DOUBLE-WORDS
	MOV NPKSAB-CHXCHS(D),(B)+
	MOV HPKSAB-CHXCHS(D),(B)+
	CLR (B)+
	CLR (B)+
	MOV NPKSGB-CHXCHS(D),(B)+
	MOV HPKSGB-CHXCHS(D),(B)+
	MOV NPKSRL-CHXCHS(D),(B)+
	MOV HPKSRL-CHXCHS(D),(B)+
	BR 59$
.ENDC ;ETHERP
55$:	CMP CHIRFL(D),#CHSRFL	;CHAOSNET CABLE?
	BNE 59$			;NO, THAT'S ALL
	MOV #16.,-10.(B)	;YES, THERE ARE 6 MORE DOUBLE-WORDS
	MOV NPKSAB-CHXCHS(D),(B)+
	MOV HPKSAB-CHXCHS(D),(B)+
	MOV NPKSLS-CHXCHS(D),(B)+
	MOV HPKSLS-CHXCHS(D),(B)+
	MOV NPKSGB-CHXCHS(D),(B)+
	MOV HPKSGB-CHXCHS(D),(B)+
	MOV NPKSRL-CHXCHS(D),(B)+
	MOV HPKSRL-CHXCHS(D),(B)+
	CLR (B)+		;I DON'T KEEP TRACK OF BIT COUNT ERRS SEPARATELY
	CLR (B)+
	MOV NPKSBD(D),(B)+
	MOV HPKSBD(D),(B)+
59$:	TST (D)+
	CMP D,#2*NCHX
	BLO 50$
RETANS:	MOVB #%COANS,PKOP(A)	;RETURN THIS PACKET TO SOURCE AS AN 'ANS'
	RET			;NOTE CONDITION CODES HAVE 'NE'

PLSSRV:	MOVB PKNBYT(A),C	;GET BYTE COUNT, SHOULD BE SMALL
	CMP C,#8		;6 FOR PULSAR, 1 FOR SPACE, 1 FOR CHARACTER
	BLO 20$			;NOT GIVEN AN ARGUMENT, JUST READ STATUS
	MOVB PKDAT+7(A),C	;YES, GET THE ARGUMENT
	SUB #'0,C		;CONVERT TO BINARY (CHEAPO!)
	MOV C,PULSON		;CHANGE PULSON STATUS
20$:	MOV #1,PKNBYT(A)	;SET BYTE LENGTH, CLEAR FORWARDING COUNT
	MOV PULSON,C		;RETURN PULSAR STATUS
	ADD #'0,C		;IN ASCII
	MOVB C,PKDAT(A)
	BR RETANS

	.SBTTL CHAOSNET INTERRUPT HANDLER

;INTERRUPT HANDLER ENTRIES
.REPT CHAOSP
CONC CHS,\.RPCNT,BK:
	JSR I,CHSBRK
	CHXCHS+<.RPCNT*2>
.ENDR

;SUBROUTINE TO ENABLE CHAOSNET INTERFACE IN H,I TO RECEIVE NEXT PACKET
CHINXT:	MOVB 1(H),A		;GET CSR BITS 9-12 (LOST COUNT)
	ASR A
	BIC #-20,A
	ADD A,NPKSLS-CHXCHS(I)
	ADC HPKSLS-CHXCHS(I)
	BIS #%CARCL+%CAREN,(H)	;MAKE READY TO RECEIVE ANOTHER MESSAGE
	RET

;COMMON CHAOS INTERRUPT ROUTINE
CHSBRK:	MOV (I),I		;GET SOURCE/SINK INDEX
	PUSH <A,B,C,D,H>	;SAVE ALL REGISTERS
	MOV CHIHWR(I),H		;GET HARDWARE ADDRESS
	MOV (H),A .SEE CH%CSR	;GET CSR
	BPL CHSBK1 		;TEST RECEIVE DONE, BRANCH IF NOT
		.SEE %CARDN	;PALX SCREWS UP IF THIS IS ON PREVIOUS LINE!
	TST CHISTS(I)		;MAKE SURE INPUT BUFFER IS IDLE
	BNE CHSBK1		;BUSY, DON'T LOOK AT RECEIVE DONE NOW
	BIT #%CAERR,A		;CRC ERROR?
	BNE CHICRC		;JUMP IF YES
	MOV CH%RBC(H),C		;BIT COUNT -1
	SUB #47.,C		;ADD 1, THEN SUBTRACT 3*16. FOR HARDWARE WORDS
	.IREPT 4, ASR C		;CONVERT TO NUMBER OF WORDS
	CMP C,#256.
	BHI CHIFLS		;THIS CAN ONLY HAPPEN IF HARDWARE BROKEN
	ADD #CH%RBF,H		;POINT H TO RECEIVE DATA REG
	MOV CHIBFP(I),D		;COPY PACKET INTO BUFFER
	CALL MOVHD
	TST (H)			;READ OUT THE 3 HARDWARE LEADER WORDS
	CMP (H),(H)
	SUB #CH%RBF,H		;RESTORE H
	BIT #%CAERR,(H)		;WAS IT READ CORRECTLY OUT OF RAM?
	BNE CHIGBG		;NO, GARBAGE
	CMP CH%RBC(H),#7777	;WAS PACKET CORRECT LENGTH?
	BNE CHIGBG		;NO, GARBAGE
	CALL CHINXT		;DONE WITH HARDWARE, ENABLE FOR NEXT
	CALL CHSIHD		;PROCESS HEADER, GET LENGTH, DEST
	BVS CHIFL0		;BRANCH IF NO GOOD
	CALL SWAB11		;SWAB IF NOT GOING TO 11-COMPATIBLE DEST
	INC CHISTS(I)		;INDICATE BUFFER READY TO SEND
	PUSH I
	CALL CHSOUT		;SEND IT OUT
	POP I
	MOV CHIHWR(I),H		;RESTORE H
	TST CHISTS(I)		;INPUT BUFFER STILL BUSY?
	BEQ CHSBK1
	BIC #%CAREN,(H)		;YES, CLEAR RECEIVE INTERRUPT ENABLE
	BR CHSBK1		;GO CHECK ON OUTPUT SIDE

;HERE WHEN A PACKET WAS RECEIVED WITHOUT ERROR, BUT AFTER
;READING OUT OF THE RAM, CRC ERROR WAS SET.  EITHER THE
;PACKET WAS THE WRONG LENGTH, OR THE RAM FAILED, OR THE
;HARDWARE RANDOMLY CLOBBERED IT.
;WE ALSO GET HERE IF THE BIT COUNT WAS NOT -1 AFTER ALL WORDS WERE READ.
CHIGBG:	ADD #1,NPKSRL-CHXCHS(I)	;LOG THE ERROR
	ADC HPKSRL-CHXCHS(I)
	MOV H,CHSRLH
	MOV CH%RBC(H),CHSRLC
	BR CHIFLS		;GO RESET RECEIVER AND CHECK OUTPUT STATUS

;HERE WHEN A PACKET IS RECEIVED WITH A CRC ERROR.  DISCARD IT,
;BUT ALSO SAVE IT IN CHSGBF, CHSGBH, CHSGBS, CHSGBC FOR DEBUGGING (IF FTGARB).
CHICRC:	ADD #1,NPKSGB-CHXCHS(I)
	ADC HPKSGB-CHXCHS(I)
.IFNZ FTGARB
	MOV H,CHSGBH
	MOV (H),CHSGBS
	MOV CH%RBC(H),CHSGBC
	ADD #CH%RBF,H
	MOV #CHSGBF,D
	MOV #PKMAX,C
	CALL MOVHD
	SUB #CH%RBF,H		;DROP INTO CHIFLS
.ENDC ;FTGARB
;HERE TO IGNORE AN INPUT PACKET AND ENABLE HARDWARE FOR NEXT
CHIFLS:	CALL CHINXT
CHIFL0:	INC NPKSIG
;HERE TO CHECK ON TRANSMIT SIDE
CHSBK1:	TSTB (H) .SEE %CATDN	;TRANSMIT DONE?
	BPL CHSBKX		;NO, EXIT
.IFNZ CHSBTB
	CLR CHSIDL(I)		;CLEAR TRANSMIT-DONE TIME-OUT
.ENDC ;CHSBTB
	MOV CHOSTS(I),A		;WAS OUTPUT IN PROGRESS?
	BEQ CHSBK6		;NO, LOOK FOR OUTPUT
	CMP A,#2		;TRANSMIT ABORT DELAY COMPLETED?
	BEQ 10$
	BIT #%CATAB,(H)		;NO, TRANSMIT ABORTED?
	BEQ CHSBK4		;NO
	ADD #1,NPKSAB-CHXCHS(I)	;YES, METER IT, AND SET CHOSTS TO
	ADC HPKSAB-CHXCHS(I)
	INC CHOSTS(I)		;2 IF THIS IS FIRST TIME, OR 0 IF SECOND TIME
	BEQ CHSBK4		;LOST TWICE IN A ROW, GIVE UP
	BR CHSBK5		;TURN OFF INTERRUPT, DELAY FOR A WHILE

10$:	MOV #-1,CHOSTS(I)	;TRANSMIT ABORT DELAY COMPLETED, SET CHOSTS TO -1
	CALL CHSXM0		;INITIATE RE-TRANSMISSION (CHOSTS ALREADY SET)
	BR CHSBKX		;DISMISS

CHSBK4:	CALL CHSODN		;OUTPUT DONE
CHSBK6:	PUSH I
	CALL CHSRUN		;INITIATE MORE TRANSFERS
	POP I
	TST CHOSTS(I)		;DID IT INITIATE TRANSMISSION?
	BNE CHSBKX		;YES, LEAVE INTERRUPT ENABLED.
	MOV CHOHWR(I),H		;RESTORE H
	TST CHXRTF(I)		;TIME TO BROADCAST ROUTING INFO?
	BNE CHORUT		;YES
	TST PULSON		;IS THIS FEATURE TURNED ON?
	BEQ CHSBK5		;NO, FLUSH
	CMP PULSAR,PULSON	;NOTHING TO DO.  TIME FOR A TEST MESSAGE?
	BNE CHSBK5		;NOPE, GO IDLE
	MOV #52525,CH%WBF(H)	;WRITE A PACKET OF 3 HEADER WORDS, 0, 52525
	CLR CH%WBF(H)
	MOV #-1,CH%WBF(H)	;TO HOST -1, WHICH IS NON-EXISTENT
CHSBK7:	TST CH%XMT(H)		;INITIATE TRANSMISSION, DON'T ENABLE INTERRUPT
CHSBK5:	BIC #%CATEN,(H)		;GO IDLE, CLEAR TRANSMIT INTERRUPT ENABLE
;HERE TO EXIT FROM CHAOS INTERRUPT.  RESTORE REGS AND RETURN FROM INT
CHSBKX:	POP <H,D,C,B,A,I>
	RTI

.IIF NZ CH%WBF-CH%MYN, .ERR FOO CODE ASSUMES CH%WBF = CH%MYN

;BROADCAST A PACKET FULL OF ROUTING INFO, SINCE WE ARE MORE OR LESS A GATEWAY
CHORUT:	MASK 6			;INHIBIT CLOCK INTERRUPTS SO COSTS DON'T CHANGE
	ADD #CH%WBF,H		;ADDRESS WRITE BUFFER
	MOV #%CORUT*400,(H)	;OPCODE
	MOV #2*<NSUBNT-1>,A	;COUNT SUBNETS WHICH WE KNOW ANYTHING ABOUT (REASONABLE COST)
	CLR B
5$:	CMP SBNCST(A),#1000
	BHIS 6$
	ADD #4,B		;THIS ONE WILL GENERATE 2 WORDS
6$:	SUB #2,A
	BPL 5$
	MOV B,(H)		;BYTE COUNT
	CLR (H)			;DESTINATION
	CLR (H)			;..
	MOV (H),(H)		;SOURCE = CH%MYN
	CLR (H)			;SOURCE INDEX
	CLR (H)			;PACKET NUMBER
	CLR (H)			;ACK NUMBER
	MOV #2*<NSUBNT-1>,A	;GO THROUGH SUBNET TABLES
	MOVB 1(H),C		;GET SUBNET THIS IS GOING OUT ON
	ASL C
	MOV SBNCST(C),C		;GET COST OF GETTING TO US FROM GUY WHO RECEIVES THIS
10$:	CMP SBNCST(A),#1000	;WAS THIS ONE INCLUDED IN BYTE COUNT?
	BHIS 11$		;NO, DON'T PUT IT IN PACKET
	MOV A,B			;FIRST WORD IS SUBNET NUMBER
	ASR B
	MOV B,(H)
	MOV SBNCST(A),B		;SECOND WORD IS COST
	ADD C,B			;WHICH MUST INCLUDE COST OF GETTING TO US
	MOV B,(H)
11$:	SUB #2,A		;NEXT SUBNET
	BPL 10$
	CLR (H)			;BROADCAST THIS PACKET
	SUB #CH%WBF,H		;RESTORE H
	CLR CHXRTF(I)		;CLEAR REQUEST FOR ROUTING PACKET
	UNMASK
	BR CHSBK7		;FIRE IT OFF, DON'T ENABLE TRANSMIT-DONE INTERRUPT

;INITIATE TRANSMISSION ON CHAOS INTERFACE
;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED.  BASHES ALL REGS.
CHSXMT:	INC CHOSTS(I)		;SET CHOSTS TO 1, TRANSMIT STARTING
CHSXM0:	MOV CHOHWR(I),H		;GET HARDWARE ADDRESS
	MOV CHOINX(I),B		;GET SOURCE SUPPLYING THE PACKET
	MOV CHIBFP(B),D		;GET PACKET ADDRESS
	ADD #CH%WBF,H		;ADDRESS THE WRITE BUFFER
	MOV CHILNG(B),C		;GET WORD COUNT
	CALL MOVDH		;COPY INTO HARDWARE
	MOV CHICBA(B),(H)	;STORE CABLE DESTINATION
	SUB #CH%WBF,H		;RESTORE H
	TST CH%XMT(H)		;TRIGGER TRANSMISSION
	BIS #%CATEN,(H)		;ENABLE DONE INTERRUPT
	RET			;PI LEVEL WILL PICK UP OUTPUT

.ENDC ;CHAOSP

.IFNZ ETHERP
	.SBTTL ETHERNET SUPPORT

;ENABLE NEXT ETHERNET PACKET TO COME IN.
;SINCE WE ONLY HAVE ONE BUFFER, THIS SETS UP THE TRANSFER RATHER
;THAN JUST ENABLING THE INTERRUPT AS THE CHAOSNET DOES.
;THAT WOULDN'T WORK ANYWAY, BECAUSE THE HARDWARE IS SO TOTALLY BRAIN-DAMAGED.
ETHRFL:	MOV CHIHWR(I),H
	ADD #10,H
	MOV #-<PKTMXW-ETHHDW+1>,(H)+	;- WORD COUNT, +1 FOR HARDWARE BUG
	MOV #ETHIBF+<ETHHDW*2>,(H)+	;BUFFER ADDRESS
	MOV #101,(H)		;START, INTERRUPT-ENABLE
	RET

;INCOMING PUP TOO BIG.  WE DON'T HAVE FRAGMENTATION, SO SEND A PUP ERROR REPORT
ETHBIG:	MOV #ETHIBF+PKDAT,A	;COPY PUP HEADER INTO DATA FIELD
	MOV A,C
	MOV #ETHIBF+PKDAT+20.,B
	.IREPT 10.,< MOV (A)+,(B)+ >
	MOV #517.,(B)+		;PACKET TOO LARGE ERROR
	MOV #DATMAX,(B)+	;MAX NUMBER OF BYTES ALLOWED
	MOV #50$,A
5$:	MOVB (A)+,(B)+		;ASCII MESSAGE
	BNE 5$
	INC B			;MESSAGE LENGTH IS EVEN.  INCLUDE CHECKSUM IN COUNT.
	SUB #ETHIBF+PKDAT,B	;GET PUP LENGTH
	MOV B,(C)+		;BUILD PUP HEADER NOW
	MOV #4,(C)+		;PUP TYPE = ERROR
	CMP (C)+,(C)+		;PUP ID SAME
	.IREPT 3,< MOV 6(C),(C)+ >	;DESTINATION = ORIGINAL SOURCE
	MOV #<ETHSBN*400+ETHHSN>,(C)+	;SOURCE = ME
	.IREPT 2,< CLR (C)+ >	;SOURCE PORT ZERO
	CALL ETHOUT		;TRANSMIT
	JMP ETHINX		;DISMISS

;The ascii message.  This isn't as destroyed as it looks.
50$:	.ASCIZ/UP Pot oalgr eotf tii  n ahCoanstep caek.t/
	.EVEN

;INPUT INTERRUPT
ETHIBK:	PUSH <A,B,C,D,H,I>
	MOV #CHXETH,I
	MOV CHIHWR(I),H
	MOV 14(H),A		;PICK UP STATUS
	CLR 14(H)		;CLEAR RECEIVE INTERRUPT ENABLE
	CMP ETHIBF+PKDAT-2,#1000	;TYPE = PUP?
	BNE ETHIIX			;NO, IGNORE PACKET
	TST 10(H)		;CHECK RESIDUAL WORD COUNT
	BEQ ETHBIG		;PACKET TOO BIG, RESPOND WITH PUP ERROR
	TST A			;CHECK COMBINED INPUT ERRORS BIT
	BMI 70$			;ERROR, IGNORE PACKET
	MOV ETHIBF+PKDAT+10,A	;GET DESTINATION HOST
	BEQ 5$			;AND SEE IF BROADCAST OR SELF
	CMP A,#<ETHSBN*400+ETHHSN>
	BNE 11$			;NO, ROUTE AS REGULAR MESSAGE
5$:	CMPB ETHIBF+PKDAT+2,#1	;PUP TYPE = ECHO-ME?
	BEQ ETHECO		;YES, ECHO IT (MAYBE TAKE THIS OUT AFTER 11 DEBUGGED)
	CMPB ETHIBF+PKDAT+2,#200	;GATEWAY INFORMATION REQUEST?
	BNE 10$
	TST ETHIBF+PKDAT+12	;NOT REALLY UNLESS DESTINATION SOCKET IS 2
	BNE 10$
	CMP ETHIBF+PKDAT+14,#2
	BNE 10$
	TST CHISTS+CHXEGT	;PSEUDO DEVICE AVAILABLE?
	BNE ETHIIX
	MOV #ETHIBF+PKDAT+4,A	;YES, SEND HIM SOME INFO
	MOV #EGTPID,B
	.IREPT 2,< MOV (A)+,(B)+ >	;COPY PUP ID
	ADD #6,A		;COPY SOURCE HOST AND SOCKET INTO DESTINATION
	.IREPT 3,< MOV (A)+,(B)+ >
	CALL ETHRT1
	MOV #CHXETH,I		;I CLOBBERED BY ETHRT1
	BR ETHIIX

10$:	TST A			;DON'T HARASS REST OF NET WITH BROADCASTS
	BEQ ETHIIX
11$:	MOV #ETHIBF+PKDAT,A	;CHECK THE CHECKSUM
	CALL PUPCKT
	BNE 60$			;BAD, COUNT AS RAM ERROR
.IF DF NDVRBF
	CMP ETHIBF+PKDAT+10,DVRHST	;SEE IF ADDRESSED TO DOVER USER
	BNE 12$
	CMP ETHIBF+PKDAT+14,DVRIDX
	BNE 12$
	CALL DVRPUP		;YES, PROCESS
	MOV #CHXETH,I
	BR ETHIIX

.ENDC ;NDVRBF
;TRANSLATE PUP AND SEND TO CHAOSNET
12$:	MOV #ETHIBF,A		;FILL IN CHAOSNET HEADER
	MOV #<%COUNC*400>,(A)+	;PKOP
	MOV ETHIBF+PKDAT+0,B	;PKNBYT (TOTAL PUP LENGTH = CHAOS DATA LENGTH)
	INC B			;ROUND UP TO AN EVEN NUMBER
	ASR B
	ASL B
	MOV B,(A)+
	MOV ETHIBF+PKDAT+10,(A)+	;PKDHST
	MOV ETHIBF+PKDAT+14,(A)+	;PKDIND (LOW HALF OF PUP PORT)
	MOV ETHIBF+PKDAT+16,(A)+	;PKSHST
	MOV ETHIBF+PKDAT+22,(A)+	;PKDIND (LOW HALF OF PUP PORT)
	MOV ETHIBF+PKDAT+6,(A)+		;PKPKN (LOW HALF OF PUP ID)
	MOV #100001,(A)+	;PKACN = PROTOCOL NUMBER
	CALL CHSIHD		;PROCESS THIS HEADER, GET LENGTH, DEST
	BVS ETHIIX		;IGNORE IF NO GOOD
	CALL SWAB10		;SWAB IF NOT GOING TO 10-COMPATIBLE DEST
	INC CHISTS(I)		;INDICATE BUFFER READY TO SEND
	CALL CHSOUT		;SEND IT OUT
	BR ETHINX		;ETHRFL WILL BE CALLED WHEN NECESSARY

60$:	ADD #1,NPKSRL-CHXCHS(I)	;COUNT ERRORS (SOFTWARE CHECKSUM)
	ADC HPKSRL-CHXCHS(I)
	BR ETHIIX

70$:	ADD #1,NPKSGB-CHXCHS(I)	;COUNT ERRORS (HARDWARE CHECKSUM)
	ADC HPKSGB-CHXCHS(I)
ETHIIX:	CALL ETHRFL		;AND READ ANOTHER PACKET
ETHINX:	POP <I,H,D,C,B,A>
	RTI

;ETHERNET PUP ECHO PROTOCOL
ETHECO:	MOV #ETHIBF+PKDAT+10,A	;INTERCHANGE SOURCE AND DESTINATION
	MOV A,B			;I DON'T BOTHER CHECKING CHECKSUM, BUT I DO GENERATE IT
	.IREPT 3, PUSH (A)+
	.IREPT 3,< MOV (A)+,(B)+ >
	.IREPT 3, POP -(A)
	MOV #<ETHSBN*400+ETHHSN>,(A)	;FIX SOURCE TO BE ME
	INCB ETHIBF+PKDAT+2	;SET PUP TYPE = 2 (I AM AN ECHO)
	CALL ETHOUT		;SEND BACK OUT ON THE ETHERNET
	BR ETHINX

;GENERAL PURPOSE ROUTINE FOR TRANSMITTING INTERNALLY-GENERATED PUPS TO
;THE ETHERNET.  FIXES THE DESTINATION ADDRESS (THIS IS HOW OTHER
;HOSTS FIGURE OUT WHAT SUBNET THEY ARE ON!), COMPUTES THE PUP CHECKSUM,
;AND INTERFACES TO THE PACKET SWITCH.  CALLED WITH SOURCE INDEX IN I.
;CALL THIS WITH A PACKET THAT ALREADY HAS ITS BYTES IN ETHERNET ORDER.
;BASHES ALL REGISTERS.
ETHOUT:	MOV CHIBFP(I),A
	ADD #PKDAT,A		;ADDRESS OF PUP
	TST 10(A)		;ONLY IF NOT BROADCASTING,
	BEQ 10$
	TSTB 11(A)		;DESTINATION ADDRESS HAVE NETWORK NUMBER?
	BNE 10$
	MOVB #ETHSBN,11(A)	;NO, PUT IT IN	
10$:	CALL PUPCKS		;INSERT CHECKSUM
	MOV #CHXETH,B
	MOV B,CHIOUX(I)
	INC CHISTS(I)
	JMP CHSOUT

;INITIATE TRANSMISSION ON ETHER INTERFACE
;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED.  BASHES ALL REGS.
;PACKET IS ALREADY SWABBED INTO ETHERNET BYTE ORDER (REVERSE OF CHAOSNET).
ETHXMT:	INC CHOSTS(I)		;SET CHOSTS TO 1, TRANSMIT STARTING
	CLR A			;NO OUTPUT START DELAY
ETHXM0:	MOV CHOHWR(I),H		;GET HARDWARE ADDRESS
	MOV CHOINX(I),B		;GET SOURCE SUPPLYING THE PACKET
	MOV CHIBFP(B),D		;GET PACKET ADDRESS
	ADD #PKDAT,D		;GET PUP ADDRESS
	MOV #1000,-(D)		;SMASH LAST 2 WORDS OF CHAOS HEADER.  TYPE=PUP
	MOV #ETHHSN,-(D)	;STORE SOURCE ADDRESS
	MOVB 14(D),1(D)		;STORE DESTINATION ADDRESS
	MOV 4(D),B		;GET PUP SIZE IN BYTES
	ADD #5,B		;CONVERT TO WORDS, ALLOW FOR ETHERNET HEADER
	ASR B
	NEG B			;HARDWARE WANTS IT NEGATIVE
	MOV B,(H)+		;OUTPUT WORD COUNT
	MOV D,(H)+		;OUTPUT BUFFER ADDRESS
	MOV A,2(H)		;OUTPUT START DELAY
	MOV #101,(H)		;START OUTPUT, ENABLE INTERRUPT
	RET			;PI LEVEL WILL FINISH

;OUTPUT DONE/ABORTED INTERRUPT
ETHOBK:	PUSH <A,B,C,D,H,I>
	MOV #CHXETH,I
	MOV CHOHWR(I),H
	MOV 4(H),A		;PICK UP STATUS BEFORE WRITING IT
	CLR 4(H)		;CLEAR INTERRUPT ENABLE
	TST A			;CHECK FOR ERROR
	BPL 10$
	ADD #1,NPKSAB-CHXCHS(I)
	ADC HPKSAB-CHXCHS(I)
	NEG CHOSTS(I)		;ERROR, ENTER RETRANSMIT MODE
	BPL 10$			;ALREADY RETRANSMITTED ONCE, PUNT
	MOV #25.,A		;WAIT 1 MS (DON'T BOTHER BEING RANDOM)
	CALL ETHXM0		;START TRANSMISSION AGAIN
	BR ETHINX		;AND EXIT

10$:	CALL CHSODN		;TRANSMISSION FINISHED
	CALL CHSRUN		;FIND MORE WORK TO DO
	BR ETHINX		;DISMISS

;CHECKSUM PUP ADDRESSED BY A.  BASHES A,B,C.
PUPCKS:	CALL PUPCK1		;COMPUTE CHECKSUM
	MOV B,(A)		;STORE CHECKSUM
	RET

;RETURN 'EQ' IF CHECKSUM MATCHES
PUPCKT:	CALL PUPCK1		;COMPUTE CHECKSUM
	CMP (A),#-1		;PACKET CHECKSUMMED?
	BEQ 5$			;NO, ALWAYS MATCH
	CMP B,(A)		;RETURN WITH CC SET FROM NEW AND OLD CKSMS
5$:	RET

;A POINTS AT PACKET, RETURN WITH A -> CHECKSUM AND CHECKSUM IN B.  BASH C.
PUPCK1:	MOV (A),C		;GET LENGTH
	DEC C			;IN WORDS NOT COUNTING CHECKSUM
	ASR C
	CLR B			;BUILD CHECKSUM IN B
10$:	ADD (A)+,B		;ONE'S COMPLEMENT ADD
	ADC B
	BPL 11$			;TRANSFER SIGN BIT INTO CARRY
	SEC
11$:	ROL B			;AND LEFT CYCLE
	SOB C,10$
	INC B			;GRONK MINUS ZERO
	BEQ 15$
	DEC B
15$:	RET

;BROADCAST ETHERNET GATEWAY INFO
ETHRUT:	MASK 5			;ENTER SUITABLE LEVEL FOR HACKING NET
	TST CHISTS+CHXEGT	;IS THE PSEUDO SOURCE THAT EMITS THE 
	BNE 99$			; PACKET AVAILABLE?  IF NOT, PUNT.
	CLR CHXRTF+CHXETH	;CLEAR REQUEST FLAG
	MOV #EGTPID,A
	CLR (A)+		;PUP ID ZERO
	CLR (A)+
	CLR (A)+		;BROADCAST DESTINATION
	CLR (A)+		;TO SOCKET 2
	MOV #2,(A)+
	CALL ETHRT1		;BUILD AND SEND GATEWAY INFO
99$:	UNMASK
	RET

BADSBP:	.WORD BADSUB			;POINTER INTO BAD SUBNETS
BADSUB:		;SUBNETS THAT SHOULD NOT HAVE INFORMATION SENT
		;ABOUT.  THIS LIST MUST BE IN INCREASING ORDER
		;AND MUST END IN 377.  
	.BYTE 004		;AI CHAOS 11 pseudo subnet (only AI PDP-10 (RIP) is on this)
	.BYTE 010		;Tech Square LCSnet (unused)
	.BYTE 011		;Tech Square LCS asynchronous line net (IP)
	.BYTE 012		;Tech Square VII LCSnet (IP)
	.BYTE 014		;Symbolics: Los Angeles-Chatsworth  land line
	.BYTE 020		;CHAOS MIT IN subnet (ask JNC)
	.BYTE 027		;Experimental asynchronous line net
	.BYTE 030		;Experimental radio broadcast net
	.BYTE 040		;Symbolics: Tech Square-Vassar St. microwave link
	.BYTE 041		;Symbolics: Cambridge-Palo Alto  land line
	.BYTE 042		;Symbolics: Palo Alto-Chatsworth land line
	.BYTE 047		;Symbolics: Cambridge-Chatsworth land line
	.BYTE 054		;S-1: 10Mb Ethernet
	.BYTE 055		;S-1: Pronet ring
	.BYTE 056		;S-1: serial line subnet
	.BYTE 057		;S-1: serial line subnet
	.BYTE 061		;Symbolics: Cambridge-Cambridge  land line
	.BYTE 062		;Symbolics: Cambridge-Washington land line
	.BYTE 064		;Symbolics: Cambridge-Houston	land line
	.BYTE 070		;Symbolics: Chatsworth-Westwood  land line
	.BYTE 072		;Atari: Cambridge-MIT		land line
	.BYTE 073		;Atari: Cambridge-Sunnyvale	land line
	.REPT 8
	.BYTE 377		;SPARES
	.ENDR
	.BYTE 377
.EVEN

ETHRT1:	MOV #BADSUB,BADSBP	;INITIAL BAD SUBNET POINTER
	MOV #EGTSBN,A		;FILL IN GATEWAY INFORMATION IN THE PUP
	CLR I			;I SUBNET*2, A EGTSBN POINTER
10$:	;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST
	CLR B			;FOR NON-GATEWAY, USE 0 AS GATEWAY ADDRESS
	TST SBNTYP(I)		;HARDWARE CONNECTION?
	BGT 11$
	MOV SBNADR(I),B		;NO, GET GATEWAY ADDRESS
11$:	cmpb i,#60
	bhi 20$			;dover, as of 1-Dec-83 can't handle more than 60
	;; FILTER OUT KNOWN BAD SUBNETS
	CMPB I,@BADSBP		;MAYBE UPDATE POINTER
	BHI 115$		; NO UPDATE NEEDED
	  INC BADSBP
115$:	CMPB I,@BADSBP		;THIS TIME, CHECK FOR EQUALITY
	BEQ 20$			;PUNT
	;; END FILTER
	MOV SBNCST(I),C		;GET COST
	CMP C,#1000		;IF NOT REACHABLE, DON'T PUT IN PACKET
	BHIS 20$
	.IREPT 3, ASR C		;DIVIDE BY 8 TO GET APPROXIMATE HOP COUNT
	CMP C,#ETHMXH		;DON'T PUT MORE THAN MAXHOPS
	BLOS 12$
	MOV #ETHMXH,C
12$:	MOV I,D			;GET TARGET-NET
	ASR D
	SWAB B
	MOVB B,(A)+		;STORE IN WIERD XEROX BYTE ORDER
	MOVB D,(A)+
	MOV B,(A)+
	MOVB C,-2(A)
20$:	TST (I)+		;NEXT SUBNET
	CMP I,#NSUBNT*2
	BLO 10$
	SUB #EGTSBN,A		;NUMBER OF DATA BYTES IN PUP
	ADD #22.,A		;FOR HEADER AND CHECKSUM
	MOV A,EGTPLN		;SET PUP LENGTH
	MOV #CHXEGT,I		;SET UP TO TRANSMIT TO ETHERNET
	JMP ETHOUT
.ENDC ;ETHERP

.IF DF NDVRBF
	.SBTTL DOVER PROTOCOL TRANSLATOR

;RFC PACKET IN A.  MUST PRESERVE I, AND RETURN 'EQ'.
DVROPN:	MOV PKPKN(A),C
	MOV PKSIND(A),B
	MOV PKSHST(A),A
	PUSH I
	CALL 5$
	POP I
	SEZ
	RET

;SET UP DOVER TO TALK TO HOST IN A, INDEX IN B, PKT# IN C, SENDING BACK AN OPN
;OR SENDING A LOS IF BUSY.  MUST WATCH FOR DUPLICATE RFC'S
;MUST BE CALLED WITH CHAOS AND ETHER INTERRUPTS MASKED
5$:	TST DVRHST		;BUSY?
	BEQ 10$			;NO
	CMP A,DVRHST
	BNE DVRBSY		;YES, TALKING TO ANOTHER HOST
	CMP B,DVRIDX
	BNE DVRBSY		;YES, TALKING TO ANOTHER GUY SAME HOST
	BR 11$			;DUPLICATE RFC

10$:	CLR DVRTIM		;FLUSH TIMEOUT
	MOV A,DVRHST
	MOV B,DVRIDX
	INC DVRLIX		;ESTABLISH UNIQUE LOCAL INDEX
	BNE 11$
	INC DVRLIX		;DON'T USE 0
11$:	CLR DVRMSK		;CLEAR THE BUFFER RING
	CLR DVRID		;FIRST PACKET TO SEND TO DOVER IS PACKET 0
	INC C			;C := FIRST PACKET ID THAT WILL COME IN FROM CHAOS
	MOV C,DVROFS
	MOV #%COOPN*400,B	;SEND AN OPN
	BR DVRST1		;REST IS LIKE STS

DVRBSY:	TST DVRPKP		;SPECIAL BUFFER BUSY?
	BNE CPOPJ0		;YES, PUNT
	MOV #DVRBF2,C		;SEND A CLS
	MOV #%COCLS*400,(C)+
	MOV #4,(C)+
	MOV A,(C)+
	MOV B,(C)+
	MOV #CHAD0,(C)+
	CLR (C)+
	CLR (C)+
	CLR (C)+
	MOV #"BU,(C)+
	MOV #"SY,(C)+
	MOV #DVRBF2,DVRPKP
	BR DVRRFL

;HERE TO SEND STS TO GUY CONNECTED TO DOVER
;MUST BE MASKED AGAINST CHAOS INTERRUPTS
DVRSTS:	MOV #%COSTS*400,B
DVRST1:	MOV #DVRBF2,A		;USE THIS BUFFER
	MOV #4,D		;NUMBER OF BYTES
DVRST2:	MOV A,C
	MOV B,(A)+		;OPCODE
	MOV D,(A)+		;NUMBER OF BYTES
	MOV DVRHST,(A)+		;DESTINATION HOST
	MOV DVRIDX,(A)+		;DESTINATION INDEX
	MOV #CHAD0,(A)+		;SOURCE HOST
	MOV DVRLIX,(A)+		;SOURCE INDEX
	CLR (A)+		;NO PACKET NUMBER
	CMP B,#%COLOS*400	;IF SENDING LOS, PUNT THE REST
	BEQ 20$
	MOV DVRID,B
	DEC B			;LAST PACKET ACKNOWLEDGED BY DOVER
	ADD DVROFS,B		;CONVERT TO CHAOSNET ID
	MOV B,(A)+		;ACKNOWLEDGE PACKET NUMBER
	MOV B,(A)+		;RECEIPT
	MOV #NDVRBF,(A)+	;WINDOW SIZE
20$:	MOV C,DVRPKP		;CAUSE PACKET TO GET SENT
	;DROP INTO DVRRFL

;HERE TO GET ANOTHER PACKET FROM THE DOVER.  THIS CAN BE EITHER A CHAOSNET
;PACKET TO BE SENT BACK TO THE APPROPRIATE GUY, OR A PUP TO GO TO THE DOVER
DVRRFL:	MOV #CHXDVR,I		;THIS MIGHT NOT BE SET UP WHEN CALLED
	TST CHISTS(I)		;PACKET SOURCE ONLY EMANATES ONE AT A TIME
	BNE CPOPJ0
	CMP CHIBFP(I),DVRPKP	;FINISHED SENDING SPECIAL PACKET?
	BNE 10$
	CLR DVRPKP		;YES, MAKE READY FOR ANOTHER
10$:	CLR CHIBFP(I)		;THIS PACKET NO LONGER BEING SENT
	MOV DVRPKP,A		;GOT SPECIAL PACKET TO SEND?
	BNE 30$			;YES, SEND IT
	TST DVRMSK		;GOT NEXT BUFFER TO SEND TO DOVER?
	BPL CPOPJ0		;NO
	CMP DVRRTR,#60.		;1-SECOND RETRANSMISSION INTERVAL ELAPSED?
	BLO CPOPJ0		;NO, DON'T SEND YET
	CLR DVRRTR		;SENDING, RESET RETRANSMISSION TIMER
	MOV DVRBFP,A
	BIC #PKFCMS,PKFC(A)	;CLEAR FORWARDING COUNT SINCE SENDING AGAIN
30$:	MOV A,CHIBFP(I)		;SEND THIS PACKET
	CALL CHSIHD		;ROUTE HIM
	BVS DVRRFL		;BAD, IGNORE
	CMP B,#CHXCHS		;SWAB IF SENDING TO 10, BUT NOT ETHERNET
	BHIS 35$
	CALL CHSSWB
35$:	INC CHISTS(I)		;INDICATE BUFFER READY TO SEND
	RET

;CALLED WITH A PUP IN ETHIBF WHICH IS FROM THE DOVER AND ADDRESSED
;TO THE GUY WHO'S TRYING TO PRINT ON IT.  MUST BE MASKED AGAINST ETHER & CHAOS INTERRUPTS.
DVRPUP:	MOVB ETHIBF+PKDAT+2,B
	CMP B,#31		;EFTP ACKNOWLEDGE?
	BNE DVRPP1
	CMP ETHIBF+PKDAT+6,DVRID	;ACKNOWLEDGING EXPECTED PACKET?
	BNE CPOPJ0		;NO, IGNORE IT
	INC DVRID		;YES, ADVANCE ID, POINTER, AND PACKET-PRESENCE MASK
	MOV DVRBFP,A
	ADD #DVRBFL,A
	CMP A,#DVRBF2
	BLO 11$
	MOV #DVRBUF,A
11$:	MOV A,DVRBFP
	ASL DVRMSK
	SETOM DVRRTR		;FAKE RETRANSMIT TIMER TO SEND NEXT PUP RIGHT AWAY
	TST CHISTS+CHXDVR	;PACKET SOURCE BUSY?
	BEQ DVRSTS		;NO, SEND AN ACKNOWLEDGEMENT TO THE CHAOSNET
CPOPJ0:	RET

DVRPP1:	MOV #22.,A		;RELATIVE ADDRESS OF ASCII STRING
	CMP B,#33		;EFTP ABORT?
	BEQ DVRERR
	MOV #44.,A		;RELATIVE ADDRESS OF ASCII STRING
	CMP B,#4		;PUP ERROR?
	BNE CPOPJ0		;IGNORE ANYTHING ELSE
DVRERR:	CLR DVRMSK		;DON'T SEND ANYTHING MORE TO THE DOVER
	MOV ETHIBF+PKDAT,C	;PUP LENGTH
	SUB A,C
	SUB #2,C		;GET LENGTH OF ASCII STRING
	ADD #ETHIBF+PKDAT,A	;GET ADDRESS OF ASCII STRING
	MOV #DVRBUF+PKDAT,B	;BUILD A LOS PACKET TO SEND BACK
	MOV C,D			;SAVE BYTE LENGTH
	INC C
	ASR C			;WORD COUNT
	BEQ 11$
10$:	MOV (A)+,(B)
	SWAB (B)+		;ALTO HAS BYTES IN THE WRONG ORDER
	SOB C,10$
11$:	MOV #%COLOS*400,B	;SEND A LOS
	MOV #DVRBUF,A
	CALL DVRST2
	CLR DVRHST		;KILL CONNECTION
	RET

;HERE IS A PACKET DIRECTED TO THE DOVER.  DO GOOD THINGS WITH IT.
;NOTE, IT HAS ALREADY BEEN SWABBED INTO ETHERNET BYTE ORDER.
DVRPKT:	MOV CHOINX(I),B		;GET SOURCE SUPPLYING THE PACKET
	MOV CHIBFP(B),A		;GET ADDRESS OF PACKET
	CLR DVRTIM		;FOREIGN HOST IS NOT IDLE
	MOVB PKOP(A),B		;DATA PACKET?
	BMI 50$			;YES
	CMP B,#%COSNS
	BNE 11$
	TST CHISTS+CHXDVR
	BNE 90$
	CALL DVRSTS		;SNS => STS
	BR 90$

11$:	CMP B,#%COCLS
	BEQ 12$			;CLS OR LOS PUNTS THE CONNECTION
	CMP B,#%COLOS
	BNE 13$
12$:	CLR DVRHST
	BR 90$

13$:	CMP B,#%COEOF		;NOTE THAT EOF IS TREATED VERY MUCH LIKE DATA!
	BNE 90$			;IGNORE ANYTHING RANDOM
50$:	MOV PKPKN(A),B		;GET ID OF DATA PACKET
	SUB DVROFS,B
	MOV DVRBFP,D		;FIND WHERE IN THE BUFFER IT GOES
	MOV #100000,C		;AND GET MASK BIT FOR IT
	SUB DVRID,B		;B := ID RELATIVE TO NEXT EXPECTED
	BEQ 53$
	CMP B,#NDVRBF
	BHIS 90$		;IGNORE DUPLICATE OR NOT IN WINDOW
51$:	ADD #DVRBFL,D
	CMP D,#DVRBF2
	BLO 52$
	MOV #DVRBUF,D
52$:	CLC
	ROR C
	SOB B,51$
53$:	BIT C,DVRMSK		;ALREADY HAVE PACKET?
	BNE 90$			;YES, IGNORE
	BIS C,DVRMSK		;NO, STORE IT AWAY
	MOV D,C
	ADD #PKDAT,D		;BUILD PUP
	MOV PKNBYT(A),B
	BIC #PKNBMS,B
	MOV B,(D)
	ADD #22.,(D)+		;PUP LENGTH
	MOV #30,(D)+		;PUP TYPE
	TST (A)			;WAS THIS DATA OR EOF?
	BMI 54$			;DATA
	SUB (PC),-2(D)		;EOF, SET PUP TYPE TO 32
54$:	CLR (D)+		;PUP ID HIGH
	MOV PKPKN(A),(D)	;PUP ID LOW
	SUB DVROFS,(D)+		; CORRECTED
	MOV #DVRADR,(D)+	;DESTINATION HOST
	CLR (D)+		;DESTINATION SOCKET HIGH
	MOV #20,(D)+		;DESTINATION SOCKET LOW
	MOV DVRHST,(D)+		;SOURCE HOST
	CLR (D)+		;SOURCE SOCKET HIGH
	MOV DVRIDX,(D)+		;SOURCE SOCKET LOW
	ADD #PKDAT,A
	INC B
	ASR B			;NUMBER OF DATA WORDS
;*** TEMPORARY KLUDGE ***
	PUSH <A,D,B>		;PUSH B LAST!!
;*** END TEMPORARY KLUDGE ***
	BEQ 56$
55$:	MOV (A)+,(D)+		;MOVE THE DATA
	SOB B,55$
56$:	MOV C,A
	ADD #PKDAT,A
	MOV #<%COUNC*400>,(C)	;PKOP
	MOV 10(A),PKDHST(C)
	MOV (A),PKNBYT(C)	;SHOULD BE ENOUGH TO GET IT ROUTED TO ETHERNET
	CALL PUPCKS		;STORE APPROPRIATE CHECKSUM
;*** TEMPORARY KLUDGE ***
	POP <B,D,A>		;LOOK FOR SOME KIND OF MACHINE FAILURE
	TST B
	BEQ 79$
70$:	CMP (D)+,(A)+
	BNE 75$
	SOB B,70$
	BR 79$

75$:	DVRFKT=.
	NOP			;PUT A BPT HERE IF YOU LIKE
	INC NDVRFK
	CLR DVRMSK		;DO IT ALL OVER AGAIN
79$:
;*** END TEMPORARY KLUDGE ***
	CALL DVRRFL		;SEND THIS PACKET MAYBE
90$:	MOV #CHXDVR,I
	JMP CHSODN		;THIS PACKET HANDLED
.ENDC ;NDVRBF
.IFNZ DL10P
	.SBTTL TRAP HANDLING

TRAP14:	HALT			;BPT WITH NO RUG IN CORE

TRAP10:	BPT			;ILLEGAL INSTRUCTION

TRAP4:	NOP			;PATCH BPT HERE IF YOU WANT
	CMP (SP),#MAIN		;IF TRAP4 IN MAIN LOOP...
	BLO CRASH
	CMP (SP),#MAINE
	BHIS CRASH
	BIT #DLXPRT,DLXCSR	;AND DL10 PORT TURNED OFF
	BNE CRASH
	TST DLXOFF		;AND WE THOUGHT IT WAS ON
	BNE CRASH
RESTRT:	MOV #STKBAS,SP		;THEN RESTART MAIN LOOP
	CLR -(SP)		;WHICH WILL WAIT FOR DL10 PORT TO TURN ON
	MOV #MAIN,-(SP)
	RTI

CRASH:	BPT			;OTHERWISE, CRASH

PWRFAL:	RESET			;POWER FAIL OR UP - IF FAIL, HALT DURING RESET
	MOV #20,B		;WAIT 2 SECONDS TO
1$:	CLR A			; MAKE SURE POWER IS REALLY ON
	SOB A,.
	SOB B,1$
	JMP INIT		;POWER SEEMS UP, RESTART PROGRAM
.ENDC ;DL10P

.IFNZ NODDT	;IF NO DDT OR OTHER "OPERATING SYSTEM", SET UP TRAP HANDLERS
TRAP4:	
	.=4
	.WORD TRAP4,340,TRAP10,340,TRAP14,340,TRAP10,340,PWRFAL,340,TRAP10,340,TRAP10,340
	.=TRAP4

;ILLEGAL ADDRESS, UNIBUS NXM, STACK OVERFLOW
TRAP4:	BPT
	0

;ILLEGAL INSTRUCTION, IOT, EMT
TRAP10:	BPT
	0

;POWER FAILURE OR RESTORE
PWRFAL:	HALT
	0

;BPT (OR TRACE)
TRAP14:	.REPT 7		;SAVE REGISTERS WHERE CARPET CAN FIND THEM
	MOV %0+.RPCNT,BPTACS+<.RPCNT*2>
	.ENDR
	CLR BPTGO
	SETOM BPTFLG
5$:	TST BPTGO
	BEQ 5$
	CLR BPTFLG
	.REPT 7
	MOV BPTACS+<.RPCNT*2>,%0+.RPCNT
	.ENDR
	RTI	

BPTFLG:	0	;NON-ZERO IF GOT A BPT
BPTGO:	0	;NON-ZERO TO PROCEED
BPTACS:	.BLKW 7	;REGS EXCEPT PC

.ENDC ;NODDT

	.SBTTL INITIALIZATION
GO::
INIT:	CLR PS
.IFNZ DL10P
	RESET
	MOV #STKBAS,SP
	TST 14
	BNE 1$			;BPT ALREADY SET UP BY RUG
	MOV #TRAP14,14
	MOV #340,16
1$:
.ENDC ;DL10P
.IFNZ NODDT			;NO OPERATING SYSTEM
	RESET
	MOV #STKBAS,SP
.ENDC ;NODDT
	SETOM DLXOFF		;REINITIALIZE VARIOUS VARIABLES
	SETOM NO.ITS
.REPT CHAOSP			;IDLE CHAOS NET INTERFACES
	CLR CHISTS+CHXCHS+<2*.RPCNT>
	CLR CHOSTS+CHXCHS+<2*.RPCNT>
.ENDR
.IIF NZ	T300P, CLR RQBACT
.IFNZ NCT
	MOV #NFTTY,I
76$:	MOV NRMIPC(I),TTYIPC(I)
	ADD #2,I
	CMP I,#LASTTY
	BLE 76$
	MOV #TYORNG,B		;CLEAR THE TYPOUT-DONE RING
	CALL CLRING
	MOV #<NFTTY/2>,A	;GIVE OUTPUT DONE ON ALL LINES
78$:	CALL PUT
	INC A
	CMP A,#<NFTTY/2>+NCT
	BLO 78$
.ENDC ;NCT
.IFNZ NDMS
;;; Turn on DM11-BBs
	CLR B			;iterated over DM11 units
	MOV #NDMS,H
5$:	MOV #DMCLR+DMCSN,@DMCSR(B)	;CLEAR SCANNER MEMORY
2$:	BIT #DMBSY,@DMCSR(B)
	BNE 2$
	CLR I			;iterated over modem channels
	;; turn on connected modem channels for one DM11
	CLR A			;counter for channels per unit
3$:	TST M2LMAP(I)
	BEQ 4$
	MOV A,@DMCSR(B)
	MOV #LINENB,@DMLSR(B)
4$:	TST (I)+
	INC A
	CMP A,#16.
	BLT 3$
	TST (B)+
	SOB H,5$		;next DM11
	;; treat first-time interrupts differently
	SETOM DMINI
	CLR B
	MOV #NDMS,A
6$:	MOV #DMSCN+DMIEN,@DMCSR(B)	;enable scanner interrupts
	TST (B)+
	SOB A,6$		;on all DMs
	MOV #20000.,A
	SOB A,.			;DELAY 50 MILLISECONDS
	CLR DMINI		;WHILE P.I. LEVEL GETS INITIAL STATUS
.ENDC ;NDMS

.IFG NDHS
;TURN ON DH11'S
	MOV #NLDHHX,H
DHINIL:	MOV DHSCR(H),A		;DEVICE ADDRESS
	MOV #100000,16(A)	;TURN ON SILO MAINTENANCE MODE, SUSPECTED OF
				;LOSING
	MOV #4000,(A)			;RESET DH11
	MOV 16(A),B			;CHECK SILO STATUS
	BIC #300,B			;THESE BITS ARE IN RAM & DON'T CLEAR
	BEQ DHSWIN			;SHOULD HAVE CLEARED MAINTENANCE MODE AND OTHER CRUD
DHSLUZ:	BPT				;LOSE
DHSWIN:	MOV #DHRENB+DHTENB,(A)		;NOW ENABLE INTERRUPTS ON DH11
	SUB #2,H
	BGE DHINIL
.ENDC ;NDHS

;TURN ON DL11S
.IFG NDLS
	MOV #NLDLHX,H
	MOV #NDLS-1,A
21$:
.IIF NZ DTE20P, BEQ 22$		;NO KBD INT ON KL10 CTY DUE TO KLDCP LOSSAGE
	MOV #103,@DLKS(H)	;ACTIVATE KEYBOARD INTERRUPT, D.T.R., READER
22$:	MOV #100,@DLPS(H)	;ACTIVATE PRINTER INTERRUPT
	SUB #2,H
	DEC A
	BPL 21$
.ENDC ;NDLS

;SET LINE PARAMETERS AND ALLOCATE BUFFERS
.IFNZ NCT
	MOV #NFTTY,I
10$:	MOV LPRVAL(I),A
	MOV BUFSIZ(I),B
	CALL SPARAM
	ADD #2,I
	CMP I,#LASTTY
	BLE 10$
.ENDC ;NCT

;TURN ON CLOCK
.IIF Z DTE20P,	MOV #100,@#LKS	;NO CLOCK INTERRUPTS IF KLDCP IS HACKING CLOCK TOO

.IFNZ DTE20P
;INITIALIZE DTE20
	MOV #37774,DLYCNT	;DMA TO BANK 0, 2 USEC DELAY
	MOV #%D3BYT,DIAG3	;DO TO10 TRANSFERS IN BYTE MODE
	MOV #MAIN,SADR		;ONLY DO INIT ONCE
.ENDC ;DTE20P
.IIF NZ TEN11P, SETOM T11I10	;CAUSE 10 TO REINITIALIZE TEN-11 CHAOS
.REPT CHAOSP
	MOV CHIHWR+CHXCHS+<2*.RPCNT>,H	;ADDRESS THE INTERFACE
   CONC	<CMP CH%MYN(H),#CHAD>,\.RPCNT	;CHECK THE HOST NUMBER SWITCHES AGAINST THE PROGRAM
	BEQ .+4
	 BPT
	BIS #%CAREN,(H)	;ENABLE CHAOS NET INPUT INT
.ENDR ;CHAOSP
.IFNZ ETHERP
	MOV CHIHWR+CHXETH,H	;ADDRESS THE INTERFACE
	MOV 16(H),A		;GET HOST NUMBER SWITCHES
	COMB A			;FIX XEROX MISTAKE
	CMPB A,#ETHHSN		;CHECK HOST NUMBER SWITCHES
	BEQ .+4
	 BPT
	MOV #CHXETH,I		;ENABLE TO RECEIVE FIRST ETHERNET PACKET
	CALL ETHRFL
.ENDC ;ETHERP
;GO
	JMP MAIN

.IFNZ GOULDP
.SBTTL GOULD PRINTER BUFFERS

GLPOIP:	GLPBFF		;NEXT BUFFER IN AT M.P. LEVEL
GLPOOP:	GLPBFF		;NEXT BUFFER OUT AT P.I. LEVEL

	.REPT NGLPBF	;ASSEMBLE THE BUFFERS
	0		.SEE GB.STA
	GLPBFF		;DUE TO PALX BUG, LEAVE .SEE ON NEXT LINE
			.SEE GB.NXT
GLPBFF==.-4
	0		.SEE GB.FF
	0		.SEE GB.NL
	0		.SEE GB.PNT
	.BLKB GLPBSZ
	.ENDR
.ENDC	;GOULDP

	.SBTTL "TTYTYP" PARAMETER FILE

T LPRVAL:
	.BLKW NCT		;DH11 PARAMETER REG

BUFFRS:	;BEGIN ALLOCATING BUFFERS HERE

.IIF NZ NCT, INFORM <BEGINNING OF BUFFERS = >,\BUFFRS
ZZ===<BUFFRS+<NCT*MAXBSZ>+3777>/4000  ;NUMBER OF K USED
.IRP ZZZZ,<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16>
.LIF EQ ZZ-.IRPCNT	;THIS IS A CRETINOUS CROCK TO GET IT COME OUT IN DECIMAL
INFORM <HIGHEST LOCATION USED = >,\BUFFRS+<NCT*MAXBSZ>,< (>,ZZZZ,<K)>
.ENDR
	
.IFNZ NCT		;TTYTYP FILE ONLY IF WE HAVE TTYS
.IF P2			;SPEED UP THE ASSEMBLY
OFF==69105	;KLUDGES SO I DON'T HAVE TO PUT KEYWORD PARAMETERS INTO PALX
40K==40000
80K==80000

.MACRO SPEED BAUD
ZZ==-1
.IIF EQ BAUD-OFF,  ZZ==0
.IIF EQ BAUD-50,   ZZ==1
.IIF EQ BAUD-75,   ZZ==2
.IIF EQ BAUD-110,  ZZ==3
.IIF EQ BAUD-134,  ZZ==4
.IIF EQ BAUD-150,  ZZ==5
.IIF EQ BAUD-200,  ZZ==6
.IIF EQ BAUD-300,  ZZ==7
.IIF EQ BAUD-600,  ZZ==10
.IIF EQ BAUD-1200, ZZ==11
.IIF EQ BAUD-1800, ZZ==12
.IIF EQ BAUD-2400, ZZ==13
.IIF EQ BAUD-4800, ZZ==14
.IIF EQ BAUD-9600, ZZ==15
.IIF EQ BAUD-80K, ZZ==16
.IIF EQ BAUD-40K, ZZ==17
.IIF LT ZZ, .ERROR UNRECOGNIZED SPEED "BAUD"
.ENDM SPEED

.MACRO IPARM N,ODFLT,IDFLT,MUMLST
.IF GE <2*N>-NFTTY
.IF LE <2*N>-LASTTY
%%.ISPEED==-1
%%.SPEED==-1
.IRP MUM,<MUMLST>
.IF NB <MUM>
 ZZ==0
 .IRPC MUMB,<MUM>
  .IIF GE .IRPCNT-2, .MEXIT
  .IIF IDN MUMB,S, .IIF EQ .IRPCNT, ZZ==1
  .IIF IDN MUMB,P, .IIF EQ .IRPCNT-1, ZZ==ZZ+1
  .IIF IDN MUMB,I, .IIF EQ .IRPCNT, ZZ==1
  .IIF IDN MUMB,S, .IIF EQ .IRPCNT-1, ZZ==ZZ+1
  .ENDM
 .IIF EQ ZZ-2, %%.'MUM
 .ENDC
.ENDM
.IF LT %%.ISPEED
 .IIF LT %%.SPEED, %%.ISPEED==IDFLT
 .IELSE %%.ISPEED==%%.SPEED
.ENDC
.IIF LT %%.SPEED, %%.SPEED==ODFLT
SPEED %%.ISPEED
IZZ==ZZ
SPEED %%.SPEED
; BUFFER SIZE IS 1/2 SECOND'S TYPING
; BUT WILL BE SUBJECT TO LIMIT OF MAXBSZ
.IIF LT ZZ-7, BZZ==5.
.IIF EQ ZZ-7, BZZ==15.
.IIF EQ ZZ-10, BZZ==30.
.IIF EQ ZZ-11, BZZ==60.
.IIF EQ ZZ-12, BZZ==90.
.IIF EQ ZZ-13, BZZ==120.
.IIF EQ ZZ-14, BZZ==240.
.IIF EQ ZZ-15, BZZ==480.
.IIF GT ZZ-15, BZZ==1000.
.=LPRVAL+<2*N>		;ASSEMBLE LINE PARAMETER WORD
.IIF NE ZZ-3, <ZZ*2000>+<IZZ*100>+3	;ISPEED, OSPEED, NO PARITY, 8 BITS, FULL DUPLEX
.IELSE <ZZ*2000>+<IZZ*100>+3+4		;110 BAUD EXTRA STOP BIT
.=BUFSIZ+<2*N>
BZZ			;ASSEMBLE BUFFER SIZE
.ENDC
.ENDC
.ENDM IPARM

;MACROS USED IN THE TTYTYP FILE:

.MACRO TTDPRT TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,300,300,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDPRT

.MACRO TTDMRX TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,600,600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDMRX

.MACRO TTDTRM TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,1200,1200,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDTRM

.MACRO TTDLPT TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,9600,9600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDLPT

.MACRO TTDLA36 TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,300,300,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDLA36

.MACRO TTDIML TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,50K,25K,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDIML

.MACRO TTDVT TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,9600,9600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDVT

.MACRO TTDTEK TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,1200,1200,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDTEK

.MACRO TTDLSR TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,2400,2400,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDLSR

.MACRO TTDDPT TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,2400,2400,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDDPT

.MACRO TTDGT40 TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,4800,4800,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDGT40

.MACRO TTDRAY TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,9600,9600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDRAY

.MACRO TTDH19 TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,9600,9600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDRAY

.MACRO TTD11 TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,4800,4800,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTD11

.MACRO TTDRAN TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,FOO,FOO,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDRAN

.MACRO TTDTV TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,FOO,FOO,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDTV

.MACRO TTDGRN TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,9600,9600,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDGRN

.MACRO TTDSTY TN,A,B,C,D,E,F,G,H,I,J
IPARM TN,FOO,FOO,<A,B,C,D,E,F,G,H,I,J>
.ENDM TTDSTY

.MACRO REPEAT N,FOO
FAKOUT:	.REPT N
FAKOUT===0
.ENDM

NSTTYS==0			;WE'RE NOT INTERESTED IN PSEUDO-TTYS
N11TYS==0			;NOR IN PDP11 TVS

.INSRT SYSTEM;TTYTYP >

.EXPUNGE ZZ,IZZ,IZZZ,BZZ,OFF,40K,80K,%%.ISPEED,%%.SPEED
.EXPUNGE TT,TY,TO,TP,TCT,HOR,VER,ROL,SPEED,ISPEED

.ENDC ;P2

.ENDC ;NCT

.END INIT
